Merge "Fix propagating invalidations to subcompositions" into androidx-main
diff --git a/activity/activity-compose/api/current.txt b/activity/activity-compose/api/current.txt
index 7561c7a..64f3a2c 100644
--- a/activity/activity-compose/api/current.txt
+++ b/activity/activity-compose/api/current.txt
@@ -1,9 +1,20 @@
// Signature format: 4.0
package androidx.activity.compose {
+ public final class BackHandlerKt {
+ method @androidx.compose.runtime.Composable public static void BackHandler(optional boolean enabled, kotlin.jvm.functions.Function0<kotlin.Unit> onBack);
+ }
+
public final class ComponentActivityKt {
method public static void setContent(androidx.activity.ComponentActivity, optional androidx.compose.runtime.CompositionReference? parent, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
+ public final class LocalOnBackPressedDispatcherOwner {
+ method public androidx.compose.runtime.ProvidableCompositionLocal<androidx.activity.OnBackPressedDispatcherOwner> asProvidableCompositionLocal();
+ method @androidx.compose.runtime.Composable public androidx.activity.OnBackPressedDispatcherOwner getCurrent();
+ property @androidx.compose.runtime.Composable public final androidx.activity.OnBackPressedDispatcherOwner current;
+ field public static final androidx.activity.compose.LocalOnBackPressedDispatcherOwner INSTANCE;
+ }
+
}
diff --git a/activity/activity-compose/api/public_plus_experimental_current.txt b/activity/activity-compose/api/public_plus_experimental_current.txt
index 7561c7a..64f3a2c 100644
--- a/activity/activity-compose/api/public_plus_experimental_current.txt
+++ b/activity/activity-compose/api/public_plus_experimental_current.txt
@@ -1,9 +1,20 @@
// Signature format: 4.0
package androidx.activity.compose {
+ public final class BackHandlerKt {
+ method @androidx.compose.runtime.Composable public static void BackHandler(optional boolean enabled, kotlin.jvm.functions.Function0<kotlin.Unit> onBack);
+ }
+
public final class ComponentActivityKt {
method public static void setContent(androidx.activity.ComponentActivity, optional androidx.compose.runtime.CompositionReference? parent, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
+ public final class LocalOnBackPressedDispatcherOwner {
+ method public androidx.compose.runtime.ProvidableCompositionLocal<androidx.activity.OnBackPressedDispatcherOwner> asProvidableCompositionLocal();
+ method @androidx.compose.runtime.Composable public androidx.activity.OnBackPressedDispatcherOwner getCurrent();
+ property @androidx.compose.runtime.Composable public final androidx.activity.OnBackPressedDispatcherOwner current;
+ field public static final androidx.activity.compose.LocalOnBackPressedDispatcherOwner INSTANCE;
+ }
+
}
diff --git a/activity/activity-compose/api/restricted_current.txt b/activity/activity-compose/api/restricted_current.txt
index 7561c7a..64f3a2c 100644
--- a/activity/activity-compose/api/restricted_current.txt
+++ b/activity/activity-compose/api/restricted_current.txt
@@ -1,9 +1,20 @@
// Signature format: 4.0
package androidx.activity.compose {
+ public final class BackHandlerKt {
+ method @androidx.compose.runtime.Composable public static void BackHandler(optional boolean enabled, kotlin.jvm.functions.Function0<kotlin.Unit> onBack);
+ }
+
public final class ComponentActivityKt {
method public static void setContent(androidx.activity.ComponentActivity, optional androidx.compose.runtime.CompositionReference? parent, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
+ public final class LocalOnBackPressedDispatcherOwner {
+ method public androidx.compose.runtime.ProvidableCompositionLocal<androidx.activity.OnBackPressedDispatcherOwner> asProvidableCompositionLocal();
+ method @androidx.compose.runtime.Composable public androidx.activity.OnBackPressedDispatcherOwner getCurrent();
+ property @androidx.compose.runtime.Composable public final androidx.activity.OnBackPressedDispatcherOwner current;
+ field public static final androidx.activity.compose.LocalOnBackPressedDispatcherOwner INSTANCE;
+ }
+
}
diff --git a/activity/activity-compose/build.gradle b/activity/activity-compose/build.gradle
index 24ccb82..6a74cad 100644
--- a/activity/activity-compose/build.gradle
+++ b/activity/activity-compose/build.gradle
@@ -32,10 +32,16 @@
dependencies {
kotlinPlugin projectOrArtifact(":compose:compiler:compiler")
+ implementation(KOTLIN_STDLIB)
+ api projectOrArtifact(":compose:runtime:runtime")
api(projectOrArtifact(":activity:activity-ktx"))
api(projectOrArtifact(":compose:ui:ui"))
- implementation(KOTLIN_STDLIB)
+ androidTestImplementation projectOrArtifact(":compose:ui:ui-test-junit4")
+ androidTestImplementation projectOrArtifact(":compose:material:material")
+ androidTestImplementation(ANDROIDX_TEST_RUNNER)
+ androidTestImplementation(JUNIT)
+ androidTestImplementation(TRUTH)
}
androidx {
diff --git a/activity/activity-compose/samples/build.gradle b/activity/activity-compose/samples/build.gradle
index f2ece87..9c9f8ee 100644
--- a/activity/activity-compose/samples/build.gradle
+++ b/activity/activity-compose/samples/build.gradle
@@ -32,7 +32,12 @@
dependencies {
kotlinPlugin projectOrArtifact(":compose:compiler:compiler")
implementation(KOTLIN_STDLIB)
+
+ compileOnly projectOrArtifact(":annotation:annotation-sampled")
+ implementation projectOrArtifact(":compose:foundation:foundation")
implementation projectOrArtifact(":activity:activity-compose")
+ implementation projectOrArtifact(":activity:activity-ktx")
+ implementation projectOrArtifact(":compose:material:material")
}
androidx {
diff --git a/activity/activity-compose/samples/src/main/java/androidx/activity/compose/samples/BackHandlerSample.kt b/activity/activity-compose/samples/src/main/java/androidx/activity/compose/samples/BackHandlerSample.kt
new file mode 100644
index 0000000..e00ba70
--- /dev/null
+++ b/activity/activity-compose/samples/src/main/java/androidx/activity/compose/samples/BackHandlerSample.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.activity.compose.samples
+
+import androidx.activity.compose.BackHandler
+import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
+import androidx.annotation.Sampled
+import androidx.compose.material.Button
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+
+@Sampled
+@Composable
+fun BackHandler() {
+ var backPressedCount by mutableStateOf(0)
+ BackHandler { backPressedCount++ }
+
+ val dispatcher = LocalOnBackPressedDispatcherOwner.current.onBackPressedDispatcher
+
+ Button(onClick = { dispatcher.onBackPressed() }) {
+ Text("Press Back count $backPressedCount")
+ }
+}
diff --git a/activity/activity-compose/src/androidTest/java/androidx/activity/compose/BackHandlerTest.kt b/activity/activity-compose/src/androidTest/java/androidx/activity/compose/BackHandlerTest.kt
new file mode 100644
index 0000000..4b88bb6
--- /dev/null
+++ b/activity/activity-compose/src/androidTest/java/androidx/activity/compose/BackHandlerTest.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.activity.compose
+
+import androidx.compose.material.Button
+import androidx.compose.material.Text
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performClick
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class BackHandlerTest {
+ @get:Rule
+ val composeTestRule = createComposeRule()
+
+ @Test
+ fun testBackHandler() {
+ var backCounter = 0
+
+ composeTestRule.setContent {
+ BackHandler { backCounter++ }
+ val dispatcher = LocalOnBackPressedDispatcherOwner.current.onBackPressedDispatcher
+ Button(onClick = { dispatcher.onBackPressed() }) {
+ Text(text = "Press Back")
+ }
+ }
+
+ composeTestRule.onNodeWithText("Press Back").performClick()
+ composeTestRule.runOnIdle {
+ assertThat(backCounter).isEqualTo(1)
+ }
+ }
+
+ @Test
+ fun testBackHandlerDisabledChild() {
+ var parentBackCounter = 0
+ var childBackCounter = 0
+
+ composeTestRule.setContent {
+ BackHandler { parentBackCounter++ }
+ val dispatcher = LocalOnBackPressedDispatcherOwner.current.onBackPressedDispatcher
+ Button(onClick = { dispatcher.onBackPressed() }) {
+ BackHandler(false) { childBackCounter++ }
+ Text(text = "Press Back")
+ }
+ }
+
+ composeTestRule.onNodeWithText("Press Back").performClick()
+ composeTestRule.runOnIdle {
+ assertThat(parentBackCounter).isEqualTo(1)
+ assertThat(childBackCounter).isEqualTo(0)
+ }
+ }
+}
diff --git a/activity/activity-compose/src/androidTest/java/androidx/activity/compose/BackPressedDispatcherOwnerTest.kt b/activity/activity-compose/src/androidTest/java/androidx/activity/compose/BackPressedDispatcherOwnerTest.kt
new file mode 100644
index 0000000..69730c3
--- /dev/null
+++ b/activity/activity-compose/src/androidTest/java/androidx/activity/compose/BackPressedDispatcherOwnerTest.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.activity.compose
+
+import androidx.activity.OnBackPressedDispatcher
+import androidx.activity.OnBackPressedDispatcherOwner
+import androidx.compose.material.Button
+import androidx.compose.material.Text
+import androidx.compose.runtime.Providers
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performClick
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class BackPressedDispatcherOwnerTest {
+ @get:Rule
+ val composeTestRule = createComposeRule()
+
+ @Test
+ fun testGetBackPressedDispatcher() {
+ lateinit var dispatcherOwner: OnBackPressedDispatcherOwner
+ composeTestRule.setContent {
+ dispatcherOwner = LocalOnBackPressedDispatcherOwner.current
+ }
+
+ assertWithMessage("There should be a dispatcherOwner set")
+ .that(dispatcherOwner)
+ .isNotNull()
+ }
+
+ @Test
+ fun testGetBackPressedDispatcherProviders() {
+ val testDispatcherOwner: OnBackPressedDispatcherOwner =
+ object : OnBackPressedDispatcherOwner {
+ override fun getLifecycle(): Lifecycle {
+ return LifecycleRegistry(this)
+ }
+
+ override fun getOnBackPressedDispatcher(): OnBackPressedDispatcher {
+ return OnBackPressedDispatcher()
+ }
+ }
+
+ var innerDispatcherOwner: OnBackPressedDispatcherOwner? = null
+
+ composeTestRule.setContent {
+ Providers(
+ LocalOnBackPressedDispatcherOwner.asProvidableCompositionLocal()
+ provides testDispatcherOwner
+ ) {
+ innerDispatcherOwner = LocalOnBackPressedDispatcherOwner.current
+ }
+ }
+
+ assertThat(innerDispatcherOwner).isEqualTo(testDispatcherOwner)
+ }
+
+ @Test
+ fun testBackHandler() {
+ var backCounter = 0
+
+ composeTestRule.setContent {
+ BackHandler { backCounter++ }
+ val dispatcher = LocalOnBackPressedDispatcherOwner.current.onBackPressedDispatcher
+ Button(onClick = { dispatcher.onBackPressed() }) {
+ Text(text = "Press Back")
+ }
+ }
+
+ composeTestRule.onNodeWithText("Press Back").performClick()
+ composeTestRule.runOnIdle {
+ assertThat(backCounter).isEqualTo(1)
+ }
+ }
+}
diff --git a/activity/activity-compose/src/main/java/androidx/activity/compose/BackHandler.kt b/activity/activity-compose/src/main/java/androidx/activity/compose/BackHandler.kt
new file mode 100644
index 0000000..38dc211
--- /dev/null
+++ b/activity/activity-compose/src/main/java/androidx/activity/compose/BackHandler.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.activity.compose
+
+import android.content.Context
+import android.content.ContextWrapper
+import androidx.activity.OnBackPressedCallback
+import androidx.activity.OnBackPressedDispatcher
+import androidx.activity.OnBackPressedDispatcherOwner
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.ProvidableCompositionLocal
+import androidx.compose.runtime.SideEffect
+import androidx.compose.runtime.compositionLocalOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.ui.platform.LocalContext
+
+/**
+ * Provides a [OnBackPressedDispatcher] that can be used by Composables hosted in a
+ * [androidx.activity.ComponentActivity].
+ */
+public object LocalOnBackPressedDispatcherOwner {
+ private val LocalOnBackPressedDispatcherOwner =
+ compositionLocalOf<OnBackPressedDispatcherOwner?> { null }
+
+ public val current: OnBackPressedDispatcherOwner
+ @Composable
+ get() = LocalOnBackPressedDispatcherOwner.current
+ ?: findOnBackPressedDispatcherOwner(LocalContext.current)
+ ?: error("No Back Dispatcher provided")
+
+ public fun asProvidableCompositionLocal():
+ ProvidableCompositionLocal<OnBackPressedDispatcherOwner?> =
+ LocalOnBackPressedDispatcherOwner
+}
+
+private fun findOnBackPressedDispatcherOwner(context: Context): OnBackPressedDispatcherOwner? {
+ var innerContext = context
+ while (innerContext is ContextWrapper) {
+ if (innerContext is OnBackPressedDispatcherOwner) {
+ return innerContext
+ }
+ innerContext = innerContext.baseContext
+ }
+ innerContext as OnBackPressedDispatcherOwner
+ return null
+}
+
+/**
+ * An effect for handling presses of the system back button.
+ *
+ * Calling this in your composable adds the given lambda to the [OnBackPressedDispatcher] of the
+ * [LocalOnBackPressedDispatcherOwner].
+ *
+ * If this is called by nested composables, if enabled, the inner most composable will consume
+ * the call to system back and invoke its lambda. The call will continue to propagate up until it
+ * finds an enabled BackHandler.
+ *
+ * @sample androidx.activity.compose.samples.BackHandler
+ *
+ * @param enabled if this BackHandler should be enabled
+ * @param onBack the action invoked by pressing the system back
+ */
+@SuppressWarnings("MissingJvmstatic")
+@Composable
+public fun BackHandler(enabled: Boolean = true, onBack: () -> Unit) {
+ // Safely update the current `onBack` lambda when a new one is provided
+ val currentOnBack = rememberUpdatedState(onBack).value
+ // Remember in Composition a back callback that calls the `onBack` lambda
+ val backCallback = remember {
+ object : OnBackPressedCallback(enabled) {
+ override fun handleOnBackPressed() {
+ currentOnBack()
+ }
+ }
+ }
+ // On every successful composition, update the callback with the `enabled` value
+ SideEffect {
+ backCallback.isEnabled = enabled
+ }
+ val backDispatcher = LocalOnBackPressedDispatcherOwner.current.onBackPressedDispatcher
+ // If `backDispatcher` changes, dispose and reset the effect
+ DisposableEffect(backDispatcher) {
+ // Add callback to the backDispatcher
+ backDispatcher.addCallback(backCallback)
+ // When the effect leaves the Composition, remove the callback
+ onDispose {
+ backCallback.remove()
+ }
+ }
+}
diff --git a/benchmark/macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoTraceProcessorTest.kt b/benchmark/macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoTraceProcessorTest.kt
index 113dca2a..e618e86 100644
--- a/benchmark/macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoTraceProcessorTest.kt
+++ b/benchmark/macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoTraceProcessorTest.kt
@@ -75,7 +75,7 @@
@Test
fun validateTraceProcessorBinariesExist() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
- val suffixes = listOf("aarch64", "arm32")
+ val suffixes = listOf("aarch64")
val entries = suffixes.map { "trace_processor_shell_$it" }.toSet()
val assets = context.assets.list("") ?: emptyArray()
assertTrue(
diff --git a/benchmark/macro/src/main/java/androidx/benchmark/macro/perfetto/PerfettoTraceProcessor.kt b/benchmark/macro/src/main/java/androidx/benchmark/macro/perfetto/PerfettoTraceProcessor.kt
index 2bd59b6..7bdd95c 100644
--- a/benchmark/macro/src/main/java/androidx/benchmark/macro/perfetto/PerfettoTraceProcessor.kt
+++ b/benchmark/macro/src/main/java/androidx/benchmark/macro/perfetto/PerfettoTraceProcessor.kt
@@ -37,7 +37,7 @@
@TestOnly
fun isAbiSupported(): Boolean {
Log.d(TAG, "Supported ABIs: ${Build.SUPPORTED_ABIS.joinToString()}")
- return !Build.SUPPORTED_ABIS.any { it == "x86" || it == "x64" }
+ return Build.SUPPORTED_64_BIT_ABIS.any { it == "arm64-v8a" }
}
/**
@@ -53,7 +53,6 @@
val suffix = when {
Build.SUPPORTED_64_BIT_ABIS.any { it.startsWith("arm") } -> "aarch64"
- Build.SUPPORTED_32_BIT_ABIS.any { it.startsWith("arm") } -> "arm32"
else -> IllegalStateException(
"Unsupported ABI (${Build.SUPPORTED_ABIS.joinToString()})"
)
diff --git a/buildSrc-tests/src/test/kotlin/androidx/build/testConfiguration/AndroidTestXmlBuilderTest.kt b/buildSrc-tests/src/test/kotlin/androidx/build/testConfiguration/AndroidTestXmlBuilderTest.kt
index 9a7b0f1d..ee7aa5d 100644
--- a/buildSrc-tests/src/test/kotlin/androidx/build/testConfiguration/AndroidTestXmlBuilderTest.kt
+++ b/buildSrc-tests/src/test/kotlin/androidx/build/testConfiguration/AndroidTestXmlBuilderTest.kt
@@ -18,7 +18,6 @@
import org.hamcrest.CoreMatchers
import org.hamcrest.MatcherAssert
-import org.junit.Assert.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -101,7 +100,13 @@
}
@Test
- fun testMultipleTags() {
+ fun testValidTestConfigXml_runFullTests() {
+ builder.runFullTests(false)
+ validate(builder.build())
+ }
+
+ @Test
+ fun testValidTestConfigXml_multipleTags() {
builder.tag("another_tag")
MatcherAssert.assertThat(builder.tags.size, CoreMatchers.`is`(2))
validate(builder.build())
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
index d28a31a..18969e22 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -35,11 +35,11 @@
val BIOMETRIC = Version("1.2.0-alpha03")
val BROWSER = Version("1.3.0-rc01")
val BUILDSRC_TESTS = Version("1.0.0-alpha01")
- val CAMERA = Version("1.1.0-alpha01")
- val CAMERA_EXTENSIONS = Version("1.0.0-alpha21")
+ val CAMERA = Version("1.1.0-alpha02")
+ val CAMERA_EXTENSIONS = Version("1.0.0-alpha22")
val CAMERA_PIPE = Version("1.0.0-alpha01")
val CAMERA_VIDEO = Version("1.0.0-alpha01")
- val CAMERA_VIEW = Version("1.0.0-alpha21")
+ val CAMERA_VIEW = Version("1.0.0-alpha22")
val CARDVIEW = Version("1.1.0-alpha01")
val CAR_APP = Version("1.0.0-alpha01")
val COLLECTION = Version("1.2.0-alpha02")
@@ -77,6 +77,7 @@
val LEGACY = Version("1.1.0-alpha01")
val LOCALBROADCASTMANAGER = Version("1.1.0-alpha02")
val LIFECYCLE = Version("2.4.0-alpha01")
+ val LIFECYCLE_COMPOSE = Version("1.0.0-alpha01")
val LIFECYCLE_EXTENSIONS = Version("2.2.0")
val LOADER = Version("1.2.0-alpha01")
val MEDIA = Version("1.3.0-beta01")
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt b/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt
index cb3c1d4..a0b077d 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt
@@ -502,6 +502,10 @@
setOf(
":compose:ui:ui-graphics",
":compose:material:material"
+ ), // Link material and material-ripple
+ setOf(
+ ":compose:material:material-ripple",
+ ":compose:material:material"
),
setOf(
":benchmark:benchmark-macro",
diff --git a/buildSrc/src/main/kotlin/androidx/build/testConfiguration/AndroidTestXmlBuilder.kt b/buildSrc/src/main/kotlin/androidx/build/testConfiguration/AndroidTestXmlBuilder.kt
index 1e70019..7cf2af5a 100644
--- a/buildSrc/src/main/kotlin/androidx/build/testConfiguration/AndroidTestXmlBuilder.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/testConfiguration/AndroidTestXmlBuilder.kt
@@ -22,6 +22,7 @@
var isBenchmark: Boolean = false
var isPostsubmit: Boolean = true
lateinit var minSdk: String
+ var runFullTests: Boolean = true
val tags: MutableList<String> = mutableListOf()
lateinit var testApkName: String
lateinit var testRunner: String
@@ -31,6 +32,7 @@
fun isBenchmark(isBenchmark: Boolean) = apply { this.isBenchmark = isBenchmark }
fun isPostsubmit(isPostsubmit: Boolean) = apply { this.isPostsubmit = isPostsubmit }
fun minSdk(minSdk: String) = apply { this.minSdk = minSdk }
+ fun runFullTests(runFullTests: Boolean) = apply { this.runFullTests = runFullTests }
fun tag(tag: String) = apply { this.tags.add(tag) }
fun testApkName(testApkName: String) = apply { this.testApkName = testApkName }
fun testRunner(testRunner: String) = apply { this.testRunner = testRunner }
@@ -61,13 +63,22 @@
.append(TEST_BLOCK_OPEN)
.append(RUNNER_OPTION.replace("TEST_RUNNER", testRunner))
.append(PACKAGE_OPTION.replace("APPLICATION_ID", applicationId))
- if (isPostsubmit)
+ if (runFullTests) {
+ if (!isPostsubmit) {
+ sb.append(FLAKY_TEST_OPTION)
+ }
sb.append(TEST_BLOCK_CLOSE)
- else {
+ } else {
+ if (!isPostsubmit) {
+ sb.append(FLAKY_TEST_OPTION)
+ }
sb.append(SMALL_TEST_OPTIONS)
.append(TEST_BLOCK_CLOSE)
.append(TEST_BLOCK_OPEN)
- .append(RUNNER_OPTION.replace("TEST_RUNNER", testRunner))
+ if (!isPostsubmit) {
+ sb.append(FLAKY_TEST_OPTION)
+ }
+ sb.append(RUNNER_OPTION.replace("TEST_RUNNER", testRunner))
.append(PACKAGE_OPTION.replace("APPLICATION_ID", applicationId))
.append(MEDIUM_TEST_OPTIONS)
.append(TEST_BLOCK_CLOSE)
@@ -84,6 +95,7 @@
var isPostsubmit: Boolean = true
var isServicePrevious: Boolean = true
lateinit var minSdk: String
+ var runFullTests: Boolean = true
lateinit var serviceApkName: String
lateinit var serviceApplicationId: String
var tags: MutableList<String> = mutableListOf()
@@ -100,6 +112,7 @@
this.isServicePrevious = isServicePrevious
}
fun minSdk(minSdk: String) = apply { this.minSdk = minSdk }
+ fun runFullTests(runFullTests: Boolean) = apply { this.runFullTests = runFullTests }
fun serviceApkName(serviceApkName: String) = apply { this.serviceApkName = serviceApkName }
fun serviceApplicationId(serviceApplicationId: String) =
apply { this.serviceApplicationId = serviceApplicationId }
@@ -145,15 +158,24 @@
.append(RUNNER_OPTION.replace("TEST_RUNNER", testRunner))
.append(PACKAGE_OPTION.replace("APPLICATION_ID", clientApplicationId))
.append(mediaInstrumentationArgs())
- if (isPostsubmit)
+ if (runFullTests) {
+ if (!isPostsubmit) {
+ sb.append(FLAKY_TEST_OPTION)
+ }
sb.append(TEST_BLOCK_CLOSE)
.append(TEST_BLOCK_OPEN)
.append(RUNNER_OPTION.replace("TEST_RUNNER", testRunner))
.append(PACKAGE_OPTION.replace("APPLICATION_ID", serviceApplicationId))
.append(mediaInstrumentationArgs())
- .append(TEST_BLOCK_CLOSE)
- else {
+ if (!isPostsubmit) {
+ sb.append(FLAKY_TEST_OPTION)
+ }
+ sb.append(TEST_BLOCK_CLOSE)
+ } else {
// add the small and medium test runners for both client and service apps
+ if (!isPostsubmit) {
+ sb.append(FLAKY_TEST_OPTION)
+ }
sb.append(SMALL_TEST_OPTIONS)
.append(TEST_BLOCK_CLOSE)
.append(TEST_BLOCK_OPEN)
@@ -161,19 +183,28 @@
.append(PACKAGE_OPTION.replace("APPLICATION_ID", clientApplicationId))
.append(mediaInstrumentationArgs())
.append(MEDIUM_TEST_OPTIONS)
- .append(TEST_BLOCK_CLOSE)
+ if (!isPostsubmit) {
+ sb.append(FLAKY_TEST_OPTION)
+ }
+ sb.append(TEST_BLOCK_CLOSE)
.append(TEST_BLOCK_OPEN)
.append(RUNNER_OPTION.replace("TEST_RUNNER", testRunner))
.append(PACKAGE_OPTION.replace("APPLICATION_ID", serviceApplicationId))
.append(mediaInstrumentationArgs())
.append(SMALL_TEST_OPTIONS)
- .append(TEST_BLOCK_CLOSE)
+ if (!isPostsubmit) {
+ sb.append(FLAKY_TEST_OPTION)
+ }
+ sb.append(TEST_BLOCK_CLOSE)
.append(TEST_BLOCK_OPEN)
.append(RUNNER_OPTION.replace("TEST_RUNNER", testRunner))
.append(PACKAGE_OPTION.replace("APPLICATION_ID", serviceApplicationId))
.append(mediaInstrumentationArgs())
.append(MEDIUM_TEST_OPTIONS)
- .append(TEST_BLOCK_CLOSE)
+ if (!isPostsubmit) {
+ sb.append(FLAKY_TEST_OPTION)
+ }
+ sb.append(TEST_BLOCK_CLOSE)
}
sb.append(CONFIGURATION_CLOSE)
return sb.toString()
@@ -286,6 +317,11 @@
""".trimIndent()
+private val FLAKY_TEST_OPTION = """
+ <option name="instrumentation-arg" key="notAnnotation" value="androidx.test.filters.FlakyTest" />
+
+""".trimIndent()
+
private val SMALL_TEST_OPTIONS = """
<option name="size" value="small" />
diff --git a/buildSrc/src/main/kotlin/androidx/build/testConfiguration/GenerateMediaTestConfigurationTask.kt b/buildSrc/src/main/kotlin/androidx/build/testConfiguration/GenerateMediaTestConfigurationTask.kt
index 5dd232a9..4bee86c 100644
--- a/buildSrc/src/main/kotlin/androidx/build/testConfiguration/GenerateMediaTestConfigurationTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/testConfiguration/GenerateMediaTestConfigurationTask.kt
@@ -152,11 +152,17 @@
.tag("androidx_unit_tests")
.tag("media_compat")
when (affectedModuleDetectorSubset.get()) {
- ProjectSubset.CHANGED_PROJECTS, ProjectSubset.ALL_AFFECTED_PROJECTS -> {
+ ProjectSubset.CHANGED_PROJECTS -> {
+ configBuilder.isPostsubmit(false)
+ configBuilder.runFullTests(true)
+ }
+ ProjectSubset.ALL_AFFECTED_PROJECTS -> {
configBuilder.isPostsubmit(true)
+ configBuilder.runFullTests(true)
}
ProjectSubset.DEPENDENT_PROJECTS -> {
configBuilder.isPostsubmit(false)
+ configBuilder.runFullTests(false)
}
else -> {
throw IllegalStateException(
diff --git a/buildSrc/src/main/kotlin/androidx/build/testConfiguration/GenerateTestConfigurationTask.kt b/buildSrc/src/main/kotlin/androidx/build/testConfiguration/GenerateTestConfigurationTask.kt
index 069b672..ac32787 100644
--- a/buildSrc/src/main/kotlin/androidx/build/testConfiguration/GenerateTestConfigurationTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/testConfiguration/GenerateTestConfigurationTask.kt
@@ -100,12 +100,18 @@
configBuilder.appApkName(appName)
}
}
- val isPostsubmit: Boolean = when (affectedModuleDetectorSubset.get()) {
- ProjectSubset.CHANGED_PROJECTS, ProjectSubset.ALL_AFFECTED_PROJECTS -> {
- true
+ when (affectedModuleDetectorSubset.get()) {
+ ProjectSubset.CHANGED_PROJECTS -> {
+ configBuilder.isPostsubmit(false)
+ configBuilder.runFullTests(true)
+ }
+ ProjectSubset.ALL_AFFECTED_PROJECTS -> {
+ configBuilder.isPostsubmit(true)
+ configBuilder.runFullTests(true)
}
ProjectSubset.DEPENDENT_PROJECTS -> {
- false
+ configBuilder.isPostsubmit(false)
+ configBuilder.runFullTests(false)
}
else -> {
throw IllegalStateException(
@@ -114,10 +120,9 @@
)
}
}
- configBuilder.isPostsubmit(isPostsubmit)
if (hasBenchmarkPlugin.get()) {
configBuilder.isBenchmark(true)
- if (isPostsubmit) {
+ if (configBuilder.isPostsubmit) {
configBuilder.tag("microbenchmarks")
} else {
configBuilder.tag("microbenchmarks_presubmit")
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
index d476693..d94d7b9 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
@@ -1663,7 +1663,7 @@
@ExecutedBy("mExecutor")
public void onOpenAvailable() {
if (mState == InternalState.PENDING_OPEN) {
- tryForceOpenCameraDevice();
+ tryOpenCameraDevice(/*fromScheduledCameraReopen=*/false);
}
}
diff --git a/camera/camera-video/build.gradle b/camera/camera-video/build.gradle
index 0463fe0..0efc3c1 100644
--- a/camera/camera-video/build.gradle
+++ b/camera/camera-video/build.gradle
@@ -58,6 +58,9 @@
androidTestImplementation(KOTLIN_COROUTINES_ANDROID)
androidTestImplementation(project(":concurrent:concurrent-futures-ktx"))
androidTestImplementation(project(":internal-testutils-truth"))
+ androidTestImplementation MOCKITO_KOTLIN, {
+ exclude group: 'org.mockito' // to keep control on the mockito version
+ }
}
android {
diff --git a/camera/camera-video/src/androidTest/AndroidManifest.xml b/camera/camera-video/src/androidTest/AndroidManifest.xml
index 7f7f316..4e99ab6 100644
--- a/camera/camera-video/src/androidTest/AndroidManifest.xml
+++ b/camera/camera-video/src/androidTest/AndroidManifest.xml
@@ -17,5 +17,6 @@
package="androidx.camera.video.test">
<uses-permission android:name="android.permission.RECORD_AUDIO" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
</manifest>
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureRotationTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureRotationTest.kt
new file mode 100644
index 0000000..98951f3
--- /dev/null
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureRotationTest.kt
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.camera.video
+
+import android.Manifest
+import android.content.ContentResolver
+import android.content.Context
+import android.media.MediaMetadataRetriever
+import android.net.Uri
+import android.os.Build
+import android.view.Surface
+import androidx.camera.camera2.Camera2Config
+import androidx.camera.core.CameraSelector
+import androidx.camera.core.CameraX
+import androidx.camera.core.VideoCapture
+import androidx.camera.core.impl.utils.CameraOrientationUtil
+import androidx.camera.core.impl.utils.executor.CameraXExecutors
+import androidx.camera.core.internal.CameraUseCaseAdapter
+import androidx.camera.testing.CameraUtil
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.LargeTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.rule.GrantPermissionRule
+import com.google.common.truth.Truth.assertThat
+import com.nhaarman.mockitokotlin2.any
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.mockito.ArgumentCaptor
+import org.mockito.Mockito
+import java.io.File
+import java.io.IOException
+import java.util.ArrayList
+import java.util.concurrent.ExecutionException
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeoutException
+
+@LargeTest
+@RunWith(Parameterized::class)
+class VideoCaptureRotationTest(
+ private var cameraSelector: CameraSelector,
+ private var targetRotation: Int
+) {
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters
+ fun data(): Collection<Array<Any>> {
+ val result: MutableList<Array<Any>> = ArrayList()
+ result.add(arrayOf(CameraSelector.DEFAULT_BACK_CAMERA, Surface.ROTATION_90))
+ result.add(arrayOf(CameraSelector.DEFAULT_BACK_CAMERA, Surface.ROTATION_180))
+ result.add(arrayOf(CameraSelector.DEFAULT_FRONT_CAMERA, Surface.ROTATION_90))
+ result.add(arrayOf(CameraSelector.DEFAULT_FRONT_CAMERA, Surface.ROTATION_180))
+ return result
+ }
+ }
+
+ private val instrumentation = InstrumentationRegistry.getInstrumentation()
+
+ @get:Rule
+ val cameraRule = CameraUtil.grantCameraPermissionAndPreTest()
+
+ @get:Rule
+ val runtimePermissionRule: GrantPermissionRule = GrantPermissionRule.grant(
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ Manifest.permission.RECORD_AUDIO
+ )
+
+ private lateinit var cameraUseCaseAdapter: CameraUseCaseAdapter
+ private lateinit var context: Context
+ private lateinit var contentResolver: ContentResolver
+ private lateinit var videoUseCase: VideoCapture
+ private lateinit var callback: VideoCapture.OnVideoSavedCallback
+ private lateinit var outputFileResultsArgumentCaptor:
+ ArgumentCaptor<VideoCapture.OutputFileResults>
+
+ @Before
+ fun setUp() {
+ // TODO(b/168175357): Fix VideoCaptureTest problems on CuttleFish API 29
+ Assume.assumeFalse(
+ "Cuttlefish has MediaCodec dequeueInput/Output buffer fails issue. Unable to test.",
+ Build.MODEL.contains("Cuttlefish") && Build.VERSION.SDK_INT == 29
+ )
+
+ // TODO(b/168187087): Video: Unable to record Video on Pixel 1 API 26,27 when only
+ // VideoCapture is bound
+ Assume.assumeFalse(
+ "Pixel running API 26 has CameraDevice.onError when set repeating request",
+ Build.DEVICE == "sailfish" &&
+ (Build.VERSION.SDK_INT == 26 || Build.VERSION.SDK_INT == 27)
+ )
+ context = ApplicationProvider.getApplicationContext()
+ CameraX.initialize(context, Camera2Config.defaultConfig())
+ Assume.assumeTrue(
+ CameraUtil.hasCameraWithLensFacing(
+ cameraSelector.lensFacing!!
+ )
+ )
+ cameraUseCaseAdapter = CameraUtil.createCameraUseCaseAdapter(context, cameraSelector)
+ contentResolver = context.contentResolver
+
+ callback = Mockito.mock(
+ VideoCapture.OnVideoSavedCallback::class.java
+ )
+ outputFileResultsArgumentCaptor = ArgumentCaptor.forClass(
+ VideoCapture.OutputFileResults::class.java
+ )
+ }
+
+ @After
+ @Throws(InterruptedException::class, ExecutionException::class, TimeoutException::class)
+ fun tearDown() {
+ instrumentation.runOnMainSync {
+ if (this::cameraUseCaseAdapter.isInitialized) {
+ cameraUseCaseAdapter.removeUseCases(cameraUseCaseAdapter.useCases)
+ }
+ }
+ CameraX.shutdown()[10000, TimeUnit.MILLISECONDS]
+ }
+
+ @Test
+ @Throws(IOException::class)
+ fun metadataGetCorrectRotation_afterVideoCaptureRecording() {
+ // Sets the device rotation.
+ videoUseCase = VideoCapture.Builder()
+ .setTargetRotation(targetRotation)
+ .build()
+ val savedFile = File.createTempFile("CameraX", ".tmp")
+ savedFile.deleteOnExit()
+
+ instrumentation.runOnMainSync {
+ try {
+ cameraUseCaseAdapter.addUseCases(setOf(videoUseCase))
+ } catch (e: CameraUseCaseAdapter.CameraException) {
+ e.printStackTrace()
+ }
+ }
+
+ // Start recording
+ videoUseCase.startRecording(
+ VideoCapture.OutputFileOptions.Builder(savedFile).build(),
+ CameraXExecutors.mainThreadExecutor(), callback
+ )
+ // The way to control recording length might not be applicable in the new VideoCapture.
+ try {
+ Thread.sleep(3000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+
+ // Assert.
+ // Checks the target rotation is correct when the use case is bound.
+ videoUseCase.stopRecording()
+
+ Mockito.verify(callback, Mockito.timeout(2000)).onVideoSaved(any())
+
+ val targetRotationDegree = CameraOrientationUtil.surfaceRotationToDegrees(targetRotation)
+ val videoRotation: Int
+ val mediaRetriever = MediaMetadataRetriever()
+
+ mediaRetriever.apply {
+ setDataSource(context, Uri.fromFile(savedFile))
+ videoRotation = extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION
+ )?.toInt()!!
+ }
+
+ val sensorRotation = CameraUtil.getSensorOrientation(cameraSelector.lensFacing!!)
+ // Whether the camera lens and display are facing opposite directions.
+ val isOpposite = cameraSelector.lensFacing == CameraSelector.LENS_FACING_BACK
+ val relativeRotation = CameraOrientationUtil.getRelativeImageRotation(
+ targetRotationDegree,
+ sensorRotation!!,
+ isOpposite
+ )
+
+ // Checks the rotation from video file's metadata is matched with the relative rotation.
+ assertThat(videoRotation).isEqualTo(relativeRotation)
+ }
+}
\ No newline at end of file
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureTest.kt
new file mode 100644
index 0000000..cdc483957
--- /dev/null
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureTest.kt
@@ -0,0 +1,694 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.camera.video
+
+import android.Manifest
+import android.content.ContentResolver
+import android.content.ContentValues
+import android.content.Context
+import android.graphics.SurfaceTexture
+import android.media.MediaMetadataRetriever
+import android.net.Uri
+import android.os.Build
+import android.os.ParcelFileDescriptor
+import android.provider.MediaStore
+import android.util.Size
+import androidx.annotation.NonNull
+import androidx.camera.camera2.Camera2Config
+import androidx.camera.core.AspectRatio
+import androidx.camera.core.CameraSelector
+import androidx.camera.core.CameraX
+import androidx.camera.core.ImageAnalysis
+import androidx.camera.core.ImageCapture
+import androidx.camera.core.ImageProxy
+import androidx.camera.core.Logger
+import androidx.camera.core.Preview
+import androidx.camera.core.Preview.SurfaceProvider
+import androidx.camera.core.UseCase
+import androidx.camera.core.VideoCapture
+import androidx.camera.core.impl.utils.executor.CameraXExecutors
+import androidx.camera.core.internal.CameraUseCaseAdapter
+import androidx.camera.core.internal.CameraUseCaseAdapter.CameraException
+import androidx.camera.testing.CameraUtil
+import androidx.camera.testing.SurfaceTextureProvider
+import androidx.camera.testing.SurfaceTextureProvider.SurfaceTextureCallback
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.rule.GrantPermissionRule
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.mockito.ArgumentCaptor
+import org.mockito.Mockito
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.verify
+import java.io.File
+import java.io.FileDescriptor
+import java.io.IOException
+import java.util.ArrayList
+import java.util.Collections
+import java.util.concurrent.ExecutionException
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeoutException
+import kotlin.math.abs
+
+@LargeTest
+@RunWith(Parameterized::class)
+class VideoCaptureTest(
+ private var cameraSelector: CameraSelector
+) {
+ companion object {
+ private const val TAG = "VideoCaptureTest"
+
+ @JvmStatic
+ @Parameterized.Parameters
+ fun data(): Collection<Array<Any>> {
+ return listOf(
+ arrayOf(CameraSelector.DEFAULT_BACK_CAMERA),
+ arrayOf(CameraSelector.DEFAULT_FRONT_CAMERA),
+ )
+ }
+ }
+
+ private val instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val context: Context = ApplicationProvider.getApplicationContext()
+
+ @get:Rule
+ val cameraRule = CameraUtil.grantCameraPermissionAndPreTest()
+
+ @get:Rule
+ val runtimePermissionRule: GrantPermissionRule = GrantPermissionRule.grant(
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ Manifest.permission.RECORD_AUDIO
+ )
+
+ private lateinit var cameraUseCaseAdapter: CameraUseCaseAdapter
+ private lateinit var contentResolver: ContentResolver
+ private lateinit var videoUseCase: VideoCapture
+ private lateinit var callback: VideoCapture.OnVideoSavedCallback
+ private lateinit var outputFileResultsArgumentCaptor:
+ ArgumentCaptor<VideoCapture.OutputFileResults>
+
+ @Before
+ fun setUp() {
+ // TODO(b/168175357): Fix VideoCaptureTest problems on CuttleFish API 29
+ assumeFalse(
+ "Cuttlefish has MediaCodec dequeueInput/Output buffer fails issue. Unable to test.",
+ Build.MODEL.contains("Cuttlefish") && Build.VERSION.SDK_INT == 29
+ )
+
+ // TODO(b/168187087): Video: Unable to record Video on Pixel 1 API 26,27 when only
+ // VideoCapture is bound
+ // On API 28 the muxer started lately just after receive the stop command, that will cause a
+ // failure.
+ assumeFalse(
+ "Pixel running API 26 has CameraDevice.onError when set repeating request",
+ Build.DEVICE == "sailfish" &&
+ (
+ Build.VERSION.SDK_INT == 26 || Build.VERSION.SDK_INT == 27 || Build.VERSION
+ .SDK_INT == 28
+ )
+ )
+
+ CameraX.initialize(context, Camera2Config.defaultConfig())
+ assumeTrue(
+ CameraUtil.hasCameraWithLensFacing(
+ cameraSelector.lensFacing!!
+ )
+ )
+ cameraUseCaseAdapter = CameraUtil.createCameraUseCaseAdapter(context, cameraSelector)
+ contentResolver = context.contentResolver
+ callback = Mockito.mock(
+ VideoCapture.OnVideoSavedCallback::class.java
+ )
+ outputFileResultsArgumentCaptor = ArgumentCaptor.forClass(
+ VideoCapture.OutputFileResults::class.java
+ )
+ }
+
+ @After
+ @Throws(InterruptedException::class, ExecutionException::class, TimeoutException::class)
+ fun tearDown() {
+ instrumentation.runOnMainSync {
+ if (this::cameraUseCaseAdapter.isInitialized) {
+ cameraUseCaseAdapter.removeUseCases(cameraUseCaseAdapter.useCases)
+ }
+ }
+ CameraX.shutdown()[10000, TimeUnit.MILLISECONDS]
+ }
+
+ @Test
+ fun canRecordingThreeVideosToFilesInARow() {
+ // Arrange.
+ videoUseCase = VideoCapture.Builder().build()
+
+ instrumentation.runOnMainSync {
+ try {
+ cameraUseCaseAdapter.addUseCases(setOf(videoUseCase))
+ } catch (e: CameraException) {
+ e.printStackTrace()
+ }
+ }
+
+ // Act.
+ // Recording 1st video
+ val savedFirstFile = File.createTempFile("CameraX00", ".tmp")
+ savedFirstFile.deleteOnExit()
+ startRecordingWithUriAndVerifyCallback(savedFirstFile)
+
+ // Recording 2nd video
+ val savedSecondFile = File.createTempFile("CameraX01", ".tmp")
+ savedSecondFile.deleteOnExit()
+ startRecordingWithUriAndVerifyCallback(savedSecondFile)
+
+ // Recording 3rd video
+ val savedThirdFile = File.createTempFile("CameraX02", ".tmp")
+ savedThirdFile.deleteOnExit()
+ startRecordingWithUriAndVerifyCallback(savedThirdFile)
+
+ val firstUri = Uri.fromFile(savedFirstFile)
+ val secondUri = Uri.fromFile(savedSecondFile)
+ val thirdUri = Uri.fromFile(savedThirdFile)
+
+ verifyRecordingResult(firstUri)
+ verifyRecordingResult(secondUri)
+ verifyRecordingResult(thirdUri)
+ }
+
+ @Ignore
+ @Test
+ fun canRecordingToFileAndStopImmediately() {
+ // Arrange.
+ videoUseCase = VideoCapture.Builder().build()
+ val savedFile = File.createTempFile("CameraX", ".tmp")
+ savedFile.deleteOnExit()
+
+ instrumentation.runOnMainSync {
+ try {
+ cameraUseCaseAdapter.addUseCases(setOf(videoUseCase))
+ } catch (e: CameraException) {
+ e.printStackTrace()
+ }
+ }
+
+ // Start recording
+ videoUseCase.startRecording(
+ VideoCapture.OutputFileOptions.Builder(savedFile).build(),
+ CameraXExecutors.mainThreadExecutor(), callback
+ )
+
+ videoUseCase.stopRecording()
+ // Assert.
+ verify(callback, Mockito.timeout(2000))
+ .onVideoSaved(outputFileResultsArgumentCaptor.capture())
+ val savedUri = outputFileResultsArgumentCaptor.value.savedUri
+ assertThat(savedUri).isNotNull()
+ assertThat(Uri.fromFile(savedFile)).isEqualTo(savedUri)
+ verifyRecordingResult(savedUri!!)
+ }
+
+ @Test
+ @Throws(IOException::class)
+ fun canRecordingWithAspectRatio4By3() {
+ // Arrange.
+ videoUseCase = VideoCapture.Builder()
+ .setTargetAspectRatio(AspectRatio.RATIO_4_3)
+ .build()
+ val savedFile = File.createTempFile("CameraX", ".tmp")
+ savedFile.deleteOnExit()
+
+ instrumentation.runOnMainSync {
+ try {
+ cameraUseCaseAdapter.addUseCases(setOf(videoUseCase))
+ } catch (e: CameraException) {
+ e.printStackTrace()
+ }
+ }
+
+ // Start recording
+ startRecordingThreeSecondsWithFile(savedFile)
+
+ videoUseCase.stopRecording()
+
+ // Assert.
+ verifyOnSavedCallback()
+
+ val mediaRetriever = MediaMetadataRetriever()
+ mediaRetriever.setDataSource(context, Uri.fromFile(savedFile))
+ val height =
+ mediaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)!!
+ .toInt().toFloat()
+ val width =
+ mediaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)!!
+ .toInt().toFloat()
+ Logger.i(TAG, "width: $width height:$height")
+ // Checks the aspect ration with a tolerance, because some devices have mod16 resolution.
+ assertThat(abs((width / height) - 4.0f / 3.0f) < 0.01).isTrue()
+ verifyRecordingResult(Uri.fromFile(savedFile))
+ }
+
+ @Test
+ @Throws(IOException::class)
+ fun canRecordingWithAspectRatio16By9() {
+ // Arrange.
+ videoUseCase = VideoCapture.Builder()
+ .setTargetAspectRatio(AspectRatio.RATIO_16_9)
+ .build()
+ val savedFile = File.createTempFile("CameraX", ".tmp")
+ savedFile.deleteOnExit()
+
+ instrumentation.runOnMainSync {
+ try {
+ cameraUseCaseAdapter.addUseCases(setOf(videoUseCase))
+ } catch (e: CameraException) {
+ e.printStackTrace()
+ }
+ }
+
+ // Start recording
+ startRecordingThreeSecondsWithFile(savedFile)
+ videoUseCase.stopRecording()
+
+ // Assert.
+ verifyOnSavedCallback()
+
+ val mediaRetriever = MediaMetadataRetriever()
+ mediaRetriever.setDataSource(context, Uri.fromFile(savedFile))
+ val height =
+ mediaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)!!
+ .toInt().toFloat()
+ val width =
+ mediaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)!!
+ .toInt().toFloat()
+ Logger.i(TAG, "width: $width height:$height")
+ // Checks the aspect ration with a tolerance, because some devices have mod16 resolution.
+ assertThat(abs((width / height) - 16.0f / 9.0f) < 0.03).isTrue()
+ verifyRecordingResult(Uri.fromFile(savedFile))
+ }
+
+ @Test
+ @Throws(IOException::class)
+ fun recordingWithPreview() {
+ // Arrange.
+ val preview: Preview = Preview.Builder().build()
+ // Sets surface provider to preview
+ instrumentation.runOnMainSync {
+ preview.setSurfaceProvider(
+ getSurfaceProvider()
+ )
+ }
+
+ videoUseCase = VideoCapture.Builder().build()
+
+ assumeTrue(checkUseCasesCombinationSupported(videoUseCase, preview))
+
+ val savedFile = File.createTempFile("CameraX", ".tmp")
+ savedFile.deleteOnExit()
+
+ addUseCaseToCamera(preview, videoUseCase)
+
+ startRecordingThreeSecondsWithFile(savedFile)
+
+ videoUseCase.stopRecording()
+ // Assert.
+ verifyOnSavedCallback()
+ verifyRecordingResult(Uri.fromFile(savedFile))
+ }
+
+ @Test
+ @Throws(IOException::class)
+ fun recordingWithImageCapture() {
+ // Arrange.
+ val imageCapture: ImageCapture = ImageCapture.Builder().build()
+ videoUseCase = VideoCapture.Builder().build()
+
+ assumeTrue(checkUseCasesCombinationSupported(videoUseCase, imageCapture))
+
+ val savedFile = File.createTempFile("CameraX", ".tmp")
+ savedFile.deleteOnExit()
+
+ addUseCaseToCamera(imageCapture, videoUseCase)
+
+ startRecordingThreeSecondsWithFile(savedFile)
+
+ videoUseCase.stopRecording()
+ // Assert.
+ verifyOnSavedCallback()
+ verifyRecordingResult(Uri.fromFile(savedFile))
+ }
+
+ @Test
+ @Throws(IOException::class)
+ fun recordingWithImageAnalysis() {
+ // Arrange.
+ val analysis = ImageAnalysis.Builder().build()
+
+ // Make ImageAnalysis active.
+ analysis.setAnalyzer(
+ CameraXExecutors.mainThreadExecutor(),
+ { obj: ImageProxy -> obj.close() }
+ )
+
+ videoUseCase = VideoCapture.Builder().build()
+
+ assumeTrue(checkUseCasesCombinationSupported(videoUseCase, analysis))
+
+ val savedFile = File.createTempFile("CameraX", ".tmp")
+ savedFile.deleteOnExit()
+
+ addUseCaseToCamera(analysis, videoUseCase)
+
+ startRecordingThreeSecondsWithFile(savedFile)
+
+ videoUseCase.stopRecording()
+ // Assert.
+ verifyOnSavedCallback()
+ verifyRecordingResult(Uri.fromFile(savedFile))
+ }
+
+ @Test
+ @Throws(IOException::class)
+ fun recordingWithPreviewAndImageAnalysis() {
+ // Arrange.
+ val preview = Preview.Builder().build()
+ // Sets surface provider to preview
+ instrumentation.runOnMainSync {
+ preview.setSurfaceProvider(
+ getSurfaceProvider()
+ )
+ }
+
+ val analysis = ImageAnalysis.Builder().build()
+ // Make ImageAnalysis active.
+ analysis.setAnalyzer(
+ CameraXExecutors.mainThreadExecutor(),
+ { obj: ImageProxy -> obj.close() }
+ )
+
+ videoUseCase = VideoCapture.Builder().build()
+
+ assumeTrue(checkUseCasesCombinationSupported(videoUseCase, preview, analysis))
+
+ val savedFile = File.createTempFile("CameraX", ".tmp")
+ savedFile.deleteOnExit()
+
+ addUseCaseToCamera(preview, analysis, videoUseCase)
+
+ startRecordingThreeSecondsWithFile(savedFile)
+
+ videoUseCase.stopRecording()
+ // Assert.
+ verifyOnSavedCallback()
+ verifyRecordingResult(Uri.fromFile(savedFile))
+ }
+
+ @Test
+ @Throws(IOException::class)
+ fun recordingWithPreviewAndImageCapture() {
+ // Arrange.
+ val preview = Preview.Builder().build()
+ // Sets surface provider to preview
+ instrumentation.runOnMainSync {
+ preview.setSurfaceProvider(
+ getSurfaceProvider()
+ )
+ }
+
+ val imageCapture = ImageCapture.Builder().build()
+
+ videoUseCase = VideoCapture.Builder().build()
+
+ assumeTrue(checkUseCasesCombinationSupported(videoUseCase, preview, imageCapture))
+
+ val savedFile = File.createTempFile("CameraX", ".tmp")
+ savedFile.deleteOnExit()
+
+ addUseCaseToCamera(preview, imageCapture, videoUseCase)
+
+ startRecordingThreeSecondsWithFile(savedFile)
+
+ videoUseCase.stopRecording()
+ // Assert.
+ verifyOnSavedCallback()
+ verifyRecordingResult(Uri.fromFile(savedFile))
+ }
+
+ @Test
+ @Throws(IOException::class)
+ fun recordingWithImageAnalysisAndImageCapture() {
+ // Arrange.
+ val imageCapture = ImageCapture.Builder().build()
+ val analysis = ImageAnalysis.Builder().build()
+ // Make ImageAnalysis active.
+ analysis.setAnalyzer(
+ CameraXExecutors.mainThreadExecutor(),
+ { obj: ImageProxy -> obj.close() }
+ )
+
+ videoUseCase = VideoCapture.Builder().build()
+
+ assumeTrue(checkUseCasesCombinationSupported(videoUseCase, analysis, imageCapture))
+
+ val savedFile = File.createTempFile("CameraX", ".tmp")
+ savedFile.deleteOnExit()
+
+ addUseCaseToCamera(analysis, imageCapture, videoUseCase)
+
+ startRecordingThreeSecondsWithFile(savedFile)
+
+ videoUseCase.stopRecording()
+ // Assert.
+ verifyOnSavedCallback()
+ verifyRecordingResult(Uri.fromFile(savedFile))
+ }
+
+ @Test
+ @Throws(IOException::class)
+ fun unbind_shouldStopRecording() {
+ val file = File.createTempFile("CameraX", "tmp")
+ file.deleteOnExit()
+
+ // Arrange.
+ videoUseCase = VideoCapture.Builder().build()
+ addUseCaseToCamera(videoUseCase)
+
+ startRecordingThreeSecondsWithFile(file)
+
+ instrumentation.runOnMainSync {
+ cameraUseCaseAdapter.removeUseCases(
+ cameraUseCaseAdapter.useCases
+ )
+ }
+
+ verify(callback, Mockito.timeout(2000))
+ .onVideoSaved(outputFileResultsArgumentCaptor.capture())
+ verifyRecordingResult(Uri.fromFile(file))
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 26)
+ fun startRecordingWithUri_whenAPILevelLargerThan26() {
+ val useCase = VideoCapture.Builder().build()
+
+ instrumentation.runOnMainSync {
+ cameraUseCaseAdapter.addUseCases(Collections.singleton<UseCase>(useCase))
+ }
+
+ val callback = Mockito.mock(VideoCapture.OnVideoSavedCallback::class.java)
+ useCase.startRecording(
+ getNewVideoOutputFileOptions(contentResolver),
+ CameraXExecutors.mainThreadExecutor(),
+ callback
+ )
+ Thread.sleep(3000)
+
+ useCase.stopRecording()
+
+ // Assert: Wait for the signal that the image has been saved.
+ val outputFileResultsArgumentCaptor =
+ ArgumentCaptor.forClass(
+ VideoCapture.OutputFileResults::class.java
+ )
+ verify(
+ callback,
+ Mockito.timeout(10000)
+ ).onVideoSaved(outputFileResultsArgumentCaptor.capture())
+
+ // get file path to remove it
+ val saveLocationUri =
+ outputFileResultsArgumentCaptor.value.savedUri
+ assertThat(saveLocationUri).isNotNull()
+ verifyRecordingResult(saveLocationUri!!)
+
+ // Remove temp test file
+ contentResolver.delete(saveLocationUri, null, null)
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 26)
+ fun startRecordingWithFileDescriptor_whenAPILevelLargerThan26() {
+ // Arrange.
+ videoUseCase = VideoCapture.Builder()
+ .build()
+ val savedFile = File.createTempFile("CameraX", ".tmp")
+ savedFile.deleteOnExit()
+
+ val fd: FileDescriptor = ParcelFileDescriptor.open(
+ savedFile,
+ ParcelFileDescriptor.MODE_READ_WRITE
+ ).fileDescriptor
+
+ instrumentation.runOnMainSync {
+ try {
+ cameraUseCaseAdapter.addUseCases(setOf(videoUseCase))
+ } catch (e: CameraException) {
+ e.printStackTrace()
+ }
+ }
+
+ // Start recording
+ videoUseCase.startRecording(
+ VideoCapture.OutputFileOptions.Builder(fd).build(),
+ CameraXExecutors.mainThreadExecutor(), callback
+ )
+
+ try {
+ Thread.sleep(3000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ videoUseCase.stopRecording()
+
+ // Assert.
+ verify(callback, Mockito.timeout(2000))
+ .onVideoSaved(outputFileResultsArgumentCaptor.capture())
+ verifyRecordingResult(Uri.fromFile(savedFile))
+ }
+
+ /** Return a VideoOutputFileOption which is used to save a video. */
+ private fun getNewVideoOutputFileOptions(
+ resolver: ContentResolver
+ ): VideoCapture.OutputFileOptions {
+ val videoFileName = "video_" + System.currentTimeMillis()
+ val contentValues = ContentValues().apply {
+ put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4")
+ put(MediaStore.Video.Media.TITLE, videoFileName)
+ put(MediaStore.Video.Media.DISPLAY_NAME, videoFileName)
+ }
+
+ return VideoCapture.OutputFileOptions.Builder(
+ resolver,
+ MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues
+ ).build()
+ }
+
+ private fun startRecordingWithUriAndVerifyCallback(file: File?) {
+ // callback need to reset since it is called multiple in same test.
+ reset(callback)
+ startRecordingThreeSecondsWithFile(file)
+
+ videoUseCase.stopRecording()
+ // Assert.
+ verify(callback, Mockito.timeout(2000))
+ .onVideoSaved(outputFileResultsArgumentCaptor.capture())
+ }
+
+ private fun addUseCaseToCamera(@NonNull vararg useCases: UseCase) {
+ val caseList: MutableList<UseCase> = ArrayList()
+ for (case in useCases) {
+ caseList.add(case)
+ }
+
+ instrumentation.runOnMainSync {
+ try {
+ cameraUseCaseAdapter.addUseCases(caseList)
+ } catch (e: CameraException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ private fun checkUseCasesCombinationSupported(@NonNull vararg useCases: UseCase): Boolean {
+ val useCaseList: MutableList<UseCase> = ArrayList()
+ for (case in useCases) {
+ useCaseList.add(case)
+ }
+
+ try {
+ cameraUseCaseAdapter.checkAttachUseCases(useCaseList)
+ } catch (e: CameraException) {
+ // This use combination is not supported on this device, abort this test.
+ Logger.i(TAG, "This combination is not supported: $useCaseList .")
+ return false
+ }
+ return true
+ }
+
+ private fun startRecordingThreeSecondsWithFile(file: File?) {
+ // Start recording
+ videoUseCase.startRecording(
+ VideoCapture.OutputFileOptions.Builder(file!!).build(),
+ CameraXExecutors.mainThreadExecutor(), callback
+ )
+
+ try {
+ Thread.sleep(3000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+
+ private fun verifyOnSavedCallback() {
+ verify(callback, Mockito.timeout(2000))
+ .onVideoSaved(outputFileResultsArgumentCaptor.capture())
+
+ val savedUri = outputFileResultsArgumentCaptor.value.savedUri
+ assertThat(savedUri).isNotNull()
+ }
+
+ private fun getSurfaceProvider(): SurfaceProvider {
+ return SurfaceTextureProvider.createSurfaceTextureProvider(object : SurfaceTextureCallback {
+ override fun onSurfaceTextureReady(surfaceTexture: SurfaceTexture, resolution: Size) {
+ // No-op
+ }
+
+ override fun onSafeToRelease(surfaceTexture: SurfaceTexture) {
+ surfaceTexture.release()
+ }
+ })
+ }
+
+ private fun verifyRecordingResult(uri: Uri) {
+ val mediaRetriever = MediaMetadataRetriever()
+ mediaRetriever.apply {
+ setDataSource(context, uri)
+ val hasAudio = extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO)
+ val hasVideo = extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO)
+
+ assertThat(hasAudio).isEqualTo("yes")
+ assertThat(hasVideo).isEqualTo("yes")
+ }
+ }
+}
\ No newline at end of file
diff --git a/car/app/app/api/res-current.txt b/car/app/app/api/res-current.txt
index e69de29..e081181 100644
--- a/car/app/app/api/res-current.txt
+++ b/car/app/app/api/res-current.txt
@@ -0,0 +1,4 @@
+attr carColorPrimary
+attr carColorPrimaryDark
+attr carColorSecondary
+attr carColorSecondaryDark
diff --git a/car/app/app/src/main/res/values/attrs.xml b/car/app/app/src/main/res/values/attrs.xml
index a481b69..6f9a1ca 100644
--- a/car/app/app/src/main/res/values/attrs.xml
+++ b/car/app/app/src/main/res/values/attrs.xml
@@ -17,8 +17,12 @@
-->
<resources>
+ <!-- The primary custom color corresponding to CarColor#PRIMARY -->
<attr name="carColorPrimary" format="color" />
+ <!-- The dark-variant primary custom color corresponding to CarColor#PRIMARY -->
<attr name="carColorPrimaryDark" format="color" />
+ <!-- The secondary custom color corresponding to CarColor#SECONDARY -->
<attr name="carColorSecondary" format="color" />
+ <!-- The dark-variant secondary custom color corresponding to CarColor#SECONDARY -->
<attr name="carColorSecondaryDark" format="color" />
</resources>
diff --git a/car/app/app/src/main/res/values/public.xml b/car/app/app/src/main/res/values/public.xml
new file mode 100644
index 0000000..7c5716b
--- /dev/null
+++ b/car/app/app/src/main/res/values/public.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+ <public name="carColorPrimary" type="attr" />
+ <public name="carColorPrimaryDark" type="attr" />
+ <public name="carColorSecondary" type="attr" />
+ <public name="carColorSecondaryDark" type="attr" />
+</resources>
diff --git a/compose/foundation/foundation-layout/api/current.txt b/compose/foundation/foundation-layout/api/current.txt
index f174f44..0de36c7 100644
--- a/compose/foundation/foundation-layout/api/current.txt
+++ b/compose/foundation/foundation-layout/api/current.txt
@@ -360,27 +360,30 @@
}
public final class PaddingKt {
+ method @androidx.compose.runtime.Stable public static androidx.compose.foundation.layout.PaddingValues PaddingValues-0680j_4(float all);
+ method @androidx.compose.runtime.Stable public static androidx.compose.foundation.layout.PaddingValues PaddingValues-ZmiikuI(optional float start, optional float top, optional float end, optional float bottom);
+ method @androidx.compose.runtime.Stable public static androidx.compose.foundation.layout.PaddingValues PaddingValues-ioHfwGI(float horizontal, float vertical);
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier absolutePadding-w2-DAAU(androidx.compose.ui.Modifier, optional float left, optional float top, optional float right, optional float bottom);
- method public static androidx.compose.ui.Modifier padding(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.PaddingValues padding);
+ method @androidx.compose.runtime.Stable public static float calculateEndPadding(androidx.compose.foundation.layout.PaddingValues, androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method @androidx.compose.runtime.Stable public static float calculateStartPadding(androidx.compose.foundation.layout.PaddingValues, androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method public static androidx.compose.ui.Modifier padding(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.PaddingValues paddingValues);
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier padding-S2lCeAQ(androidx.compose.ui.Modifier, optional float horizontal, optional float vertical);
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier padding-w2-DAAU(androidx.compose.ui.Modifier, optional float start, optional float top, optional float end, optional float bottom);
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier padding-wxomhCo(androidx.compose.ui.Modifier, float all);
}
- @androidx.compose.runtime.Immutable public final class PaddingValues {
- method public float component1-D9Ej5fM();
- method public float component2-D9Ej5fM();
- method public float component3-D9Ej5fM();
- method public float component4-D9Ej5fM();
- method @androidx.compose.runtime.Immutable public androidx.compose.foundation.layout.PaddingValues copy-ZmiikuI(float start, float top, float end, float bottom);
- method public float getBottom-D9Ej5fM();
- method public float getEnd-D9Ej5fM();
- method public float getStart-D9Ej5fM();
- method public float getTop-D9Ej5fM();
- property public final float bottom;
- property public final float end;
- property public final float start;
- property public final float top;
+ @androidx.compose.runtime.Immutable public interface PaddingValues {
+ method @androidx.compose.runtime.Stable public float calculateBottomPadding-D9Ej5fM();
+ method @androidx.compose.runtime.Stable public float calculateLeftPadding-D9Ej5fM(androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method @androidx.compose.runtime.Stable public float calculateRightPadding-D9Ej5fM(androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method @androidx.compose.runtime.Stable public float calculateTopPadding-D9Ej5fM();
+ }
+
+ @androidx.compose.runtime.Immutable public static final class PaddingValues.Absolute implements androidx.compose.foundation.layout.PaddingValues {
+ method public float calculateBottomPadding-D9Ej5fM();
+ method public float calculateLeftPadding-D9Ej5fM(androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method public float calculateRightPadding-D9Ej5fM(androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method public float calculateTopPadding-D9Ej5fM();
}
public final class RowColumnImplKt {
diff --git a/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt b/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt
index f174f44..0de36c7 100644
--- a/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt
+++ b/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt
@@ -360,27 +360,30 @@
}
public final class PaddingKt {
+ method @androidx.compose.runtime.Stable public static androidx.compose.foundation.layout.PaddingValues PaddingValues-0680j_4(float all);
+ method @androidx.compose.runtime.Stable public static androidx.compose.foundation.layout.PaddingValues PaddingValues-ZmiikuI(optional float start, optional float top, optional float end, optional float bottom);
+ method @androidx.compose.runtime.Stable public static androidx.compose.foundation.layout.PaddingValues PaddingValues-ioHfwGI(float horizontal, float vertical);
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier absolutePadding-w2-DAAU(androidx.compose.ui.Modifier, optional float left, optional float top, optional float right, optional float bottom);
- method public static androidx.compose.ui.Modifier padding(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.PaddingValues padding);
+ method @androidx.compose.runtime.Stable public static float calculateEndPadding(androidx.compose.foundation.layout.PaddingValues, androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method @androidx.compose.runtime.Stable public static float calculateStartPadding(androidx.compose.foundation.layout.PaddingValues, androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method public static androidx.compose.ui.Modifier padding(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.PaddingValues paddingValues);
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier padding-S2lCeAQ(androidx.compose.ui.Modifier, optional float horizontal, optional float vertical);
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier padding-w2-DAAU(androidx.compose.ui.Modifier, optional float start, optional float top, optional float end, optional float bottom);
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier padding-wxomhCo(androidx.compose.ui.Modifier, float all);
}
- @androidx.compose.runtime.Immutable public final class PaddingValues {
- method public float component1-D9Ej5fM();
- method public float component2-D9Ej5fM();
- method public float component3-D9Ej5fM();
- method public float component4-D9Ej5fM();
- method @androidx.compose.runtime.Immutable public androidx.compose.foundation.layout.PaddingValues copy-ZmiikuI(float start, float top, float end, float bottom);
- method public float getBottom-D9Ej5fM();
- method public float getEnd-D9Ej5fM();
- method public float getStart-D9Ej5fM();
- method public float getTop-D9Ej5fM();
- property public final float bottom;
- property public final float end;
- property public final float start;
- property public final float top;
+ @androidx.compose.runtime.Immutable public interface PaddingValues {
+ method @androidx.compose.runtime.Stable public float calculateBottomPadding-D9Ej5fM();
+ method @androidx.compose.runtime.Stable public float calculateLeftPadding-D9Ej5fM(androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method @androidx.compose.runtime.Stable public float calculateRightPadding-D9Ej5fM(androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method @androidx.compose.runtime.Stable public float calculateTopPadding-D9Ej5fM();
+ }
+
+ @androidx.compose.runtime.Immutable public static final class PaddingValues.Absolute implements androidx.compose.foundation.layout.PaddingValues {
+ method public float calculateBottomPadding-D9Ej5fM();
+ method public float calculateLeftPadding-D9Ej5fM(androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method public float calculateRightPadding-D9Ej5fM(androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method public float calculateTopPadding-D9Ej5fM();
}
public final class RowColumnImplKt {
diff --git a/compose/foundation/foundation-layout/api/restricted_current.txt b/compose/foundation/foundation-layout/api/restricted_current.txt
index ed398b4..dbc21cb 100644
--- a/compose/foundation/foundation-layout/api/restricted_current.txt
+++ b/compose/foundation/foundation-layout/api/restricted_current.txt
@@ -363,27 +363,30 @@
}
public final class PaddingKt {
+ method @androidx.compose.runtime.Stable public static androidx.compose.foundation.layout.PaddingValues PaddingValues-0680j_4(float all);
+ method @androidx.compose.runtime.Stable public static androidx.compose.foundation.layout.PaddingValues PaddingValues-ZmiikuI(optional float start, optional float top, optional float end, optional float bottom);
+ method @androidx.compose.runtime.Stable public static androidx.compose.foundation.layout.PaddingValues PaddingValues-ioHfwGI(float horizontal, float vertical);
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier absolutePadding-w2-DAAU(androidx.compose.ui.Modifier, optional float left, optional float top, optional float right, optional float bottom);
- method public static androidx.compose.ui.Modifier padding(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.PaddingValues padding);
+ method @androidx.compose.runtime.Stable public static float calculateEndPadding(androidx.compose.foundation.layout.PaddingValues, androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method @androidx.compose.runtime.Stable public static float calculateStartPadding(androidx.compose.foundation.layout.PaddingValues, androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method public static androidx.compose.ui.Modifier padding(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.PaddingValues paddingValues);
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier padding-S2lCeAQ(androidx.compose.ui.Modifier, optional float horizontal, optional float vertical);
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier padding-w2-DAAU(androidx.compose.ui.Modifier, optional float start, optional float top, optional float end, optional float bottom);
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier padding-wxomhCo(androidx.compose.ui.Modifier, float all);
}
- @androidx.compose.runtime.Immutable public final class PaddingValues {
- method public float component1-D9Ej5fM();
- method public float component2-D9Ej5fM();
- method public float component3-D9Ej5fM();
- method public float component4-D9Ej5fM();
- method @androidx.compose.runtime.Immutable public androidx.compose.foundation.layout.PaddingValues copy-ZmiikuI(float start, float top, float end, float bottom);
- method public float getBottom-D9Ej5fM();
- method public float getEnd-D9Ej5fM();
- method public float getStart-D9Ej5fM();
- method public float getTop-D9Ej5fM();
- property public final float bottom;
- property public final float end;
- property public final float start;
- property public final float top;
+ @androidx.compose.runtime.Immutable public interface PaddingValues {
+ method @androidx.compose.runtime.Stable public float calculateBottomPadding-D9Ej5fM();
+ method @androidx.compose.runtime.Stable public float calculateLeftPadding-D9Ej5fM(androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method @androidx.compose.runtime.Stable public float calculateRightPadding-D9Ej5fM(androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method @androidx.compose.runtime.Stable public float calculateTopPadding-D9Ej5fM();
+ }
+
+ @androidx.compose.runtime.Immutable public static final class PaddingValues.Absolute implements androidx.compose.foundation.layout.PaddingValues {
+ method public float calculateBottomPadding-D9Ej5fM();
+ method public float calculateLeftPadding-D9Ej5fM(androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method public float calculateRightPadding-D9Ej5fM(androidx.compose.ui.unit.LayoutDirection layoutDirection);
+ method public float calculateTopPadding-D9Ej5fM();
}
public final class RowColumnImplKt {
diff --git a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/LayoutTest.kt b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/LayoutTest.kt
index f5361fb..1b945db 100644
--- a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/LayoutTest.kt
+++ b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/LayoutTest.kt
@@ -381,8 +381,10 @@
height?.roundToPx() ?: constraints.maxHeight.roundToPx()
)
)
- val totalHorizontal = padding.start.roundToPx() + padding.end.roundToPx()
- val totalVertical = padding.top.roundToPx() + padding.bottom.roundToPx()
+ val totalHorizontal = padding.calculateLeftPadding(layoutDirection).roundToPx() +
+ padding.calculateRightPadding(layoutDirection).roundToPx()
+ val totalVertical = padding.calculateTopPadding().roundToPx() +
+ padding.calculateBottomPadding().roundToPx()
val childConstraints = containerConstraints
.copy(minWidth = 0, minHeight = 0)
.offset(-totalHorizontal, -totalVertical)
@@ -413,9 +415,9 @@
IntSize(containerWidth, containerHeight),
layoutDirection
)
- it.placeRelative(
- padding.start.roundToPx() + position.x,
- padding.top.roundToPx() + position.y
+ it.place(
+ padding.calculateLeftPadding(layoutDirection).roundToPx() + position.x,
+ padding.calculateTopPadding().roundToPx() + position.y
)
}
}
diff --git a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/PaddingTest.kt b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/PaddingTest.kt
index 00af6b8..7693010 100644
--- a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/PaddingTest.kt
+++ b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/PaddingTest.kt
@@ -130,15 +130,15 @@
}
/**
- * Tests the top-level [padding] modifier factory with a single [androidx.compose.foundation.layout
- * .PaddingValues] argument, checking that padding is applied to a child when plenty of space
+ * Tests the top-level [padding] modifier factory with a single [PaddingValues]
+ * argument, checking that padding is applied to a child when plenty of space
* is available for both content and padding.
*/
@Test
fun paddingPaddingValuesAppliedToChild() = with(density) {
val padding = PaddingValues(start = 1.dp, top = 3.dp, end = 6.dp, bottom = 10.dp)
testPaddingWithDifferentInsetsImplementation(
- padding.start, padding.top, padding.end, padding.bottom
+ 1.dp, 3.dp, 6.dp, 10.dp
) { child: @Composable () -> Unit ->
TestBox(modifier = Modifier.padding(padding), content = child)
}
@@ -167,6 +167,21 @@
}
/**
+ * Tests the top-level [absolutePadding] modifier factory with a single [PaddingValues.Absolute]
+ * argument, checking that padding is applied to a child when plenty of space
+ * is available for both content and padding.
+ */
+ @Test
+ fun paddingAbsolutePaddingValuesAppliedToChild() = with(density) {
+ val padding = PaddingValues.Absolute(left = 1.dp, top = 3.dp, right = 6.dp, bottom = 10.dp)
+ testPaddingWithDifferentInsetsImplementation(
+ 1.dp, 3.dp, 6.dp, 10.dp
+ ) { child: @Composable () -> Unit ->
+ TestBox(modifier = Modifier.padding(padding), content = child)
+ }
+ }
+
+ /**
* Tests the result of the [padding] modifier factory when not enough space is
* available to accommodate both the padding and the content. In this case, the padding
* should still be applied, modifying the final position of the content by its left and top
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Padding.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Padding.kt
index 69fff89..e1bb6e1 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Padding.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Padding.kt
@@ -134,20 +134,13 @@
* Example usage:
* @sample androidx.compose.foundation.layout.samples.PaddingValuesModifier
*/
-fun Modifier.padding(padding: PaddingValues) =
+fun Modifier.padding(paddingValues: PaddingValues) =
this.then(
- PaddingModifier(
- start = padding.start,
- top = padding.top,
- end = padding.end,
- bottom = padding.bottom,
- rtlAware = true,
+ PaddingValuesModifier(
+ paddingValues = paddingValues,
inspectorInfo = debugInspectorInfo {
name = "padding"
- properties["start"] = padding.start
- properties["top"] = padding.top
- properties["end"] = padding.end
- properties["bottom"] = padding.bottom
+ properties["paddingValues"] = paddingValues
}
)
)
@@ -186,6 +179,159 @@
)
)
+/**
+ * Describes a padding to be applied along the edges inside a box.
+ * See the [PaddingValues] factories and [Absolute] for convenient ways to
+ * build [PaddingValues].
+ */
+@Immutable
+interface PaddingValues {
+ /**
+ * The padding to be applied along the left edge inside a box.
+ */
+ @Stable
+ fun calculateLeftPadding(layoutDirection: LayoutDirection): Dp
+ /**
+ * The padding to be applied along the top edge inside a box.
+ */
+ @Stable
+ fun calculateTopPadding(): Dp
+ /**
+ * The padding to be applied along the right edge inside a box.
+ */
+ @Stable
+ fun calculateRightPadding(layoutDirection: LayoutDirection): Dp
+ /**
+ * The padding to be applied along the bottom edge inside a box.
+ */
+ @Stable
+ fun calculateBottomPadding(): Dp
+
+ /**
+ * Describes an absolute (RTL unaware) padding to be applied along the edges inside a box.
+ */
+ @Immutable
+ class Absolute(
+ @Stable
+ private val left: Dp = 0.dp,
+ @Stable
+ private val top: Dp = 0.dp,
+ @Stable
+ private val right: Dp = 0.dp,
+ @Stable
+ private val bottom: Dp = 0.dp
+ ) : PaddingValues {
+ override fun calculateLeftPadding(layoutDirection: LayoutDirection) = left
+
+ override fun calculateTopPadding() = top
+
+ override fun calculateRightPadding(layoutDirection: LayoutDirection) = right
+
+ override fun calculateBottomPadding() = bottom
+
+ override fun equals(other: Any?): Boolean {
+ if (other !is Absolute) return false
+ return left == other.left &&
+ top == other.top &&
+ right == other.right &&
+ bottom == other.bottom
+ }
+
+ override fun hashCode() =
+ ((left.hashCode() * 31 + top.hashCode()) * 31 + right.hashCode()) *
+ 31 + bottom.hashCode()
+
+ override fun toString() =
+ "PaddingValues.Absolute(left=$left, top=$top, right=$right, bottom=$bottom"
+ }
+}
+
+/**
+ * The padding to be applied along the start edge inside a box: along the left edge if
+ * the layout direction is LTR, or along the right edge for RTL.
+ */
+@Stable
+fun PaddingValues.calculateStartPadding(layoutDirection: LayoutDirection) =
+ if (layoutDirection == LayoutDirection.Ltr) {
+ calculateLeftPadding(layoutDirection)
+ } else {
+ calculateRightPadding(layoutDirection)
+ }
+
+/**
+ * The padding to be applied along the end edge inside a box: along the right edge if
+ * the layout direction is LTR, or along the left edge for RTL.
+ */
+@Stable
+fun PaddingValues.calculateEndPadding(layoutDirection: LayoutDirection) =
+ if (layoutDirection == LayoutDirection.Ltr) {
+ calculateRightPadding(layoutDirection)
+ } else {
+ calculateLeftPadding(layoutDirection)
+ }
+
+/**
+ * Creates a padding of [all] dp along all 4 edges.
+ */
+@Stable
+fun PaddingValues(all: Dp): PaddingValues = PaddingValuesImpl(all, all, all, all)
+
+/**
+ * Creates a padding of [horizontal] dp along the left and right edges, and of [vertical]
+ * dp along the top and bottom edges.
+ */
+@Stable
+fun PaddingValues(horizontal: Dp, vertical: Dp): PaddingValues =
+ PaddingValuesImpl(horizontal, vertical, horizontal, vertical)
+
+/**
+ * Creates a padding to be applied along the edges inside a box. In LTR contexts [start] will
+ * be applied along the left edge and [end] will be applied along the right edge. In RTL contexts,
+ * [start] will correspond to the right edge and [end] to the left.
+ */
+@Stable
+fun PaddingValues(
+ start: Dp = 0.dp,
+ top: Dp = 0.dp,
+ end: Dp = 0.dp,
+ bottom: Dp = 0.dp
+): PaddingValues = PaddingValuesImpl(start, top, end, bottom)
+
+@Immutable
+internal class PaddingValuesImpl(
+ @Stable
+ val start: Dp = 0.dp,
+ @Stable
+ val top: Dp = 0.dp,
+ @Stable
+ val end: Dp = 0.dp,
+ @Stable
+ val bottom: Dp = 0.dp
+) : PaddingValues {
+ override fun calculateLeftPadding(layoutDirection: LayoutDirection) =
+ if (layoutDirection == LayoutDirection.Ltr) start else end
+
+ override fun calculateTopPadding() = top
+
+ override fun calculateRightPadding(layoutDirection: LayoutDirection) =
+ if (layoutDirection == LayoutDirection.Ltr) end else start
+
+ override fun calculateBottomPadding() = bottom
+
+ override fun equals(other: Any?): Boolean {
+ if (other !is PaddingValuesImpl) return false
+ return start == other.start &&
+ top == other.top &&
+ end == other.end &&
+ bottom == other.bottom
+ }
+
+ override fun hashCode() =
+ ((start.hashCode() * 31 + top.hashCode()) * 31 + end.hashCode()) * 31 + bottom.hashCode()
+
+ override fun toString() = "PaddingValues(start=$start, top=$top, end=$end, bottom=$bottom"
+}
+
private class PaddingModifier(
val start: Dp = 0.dp,
val top: Dp = 0.dp,
@@ -209,6 +355,7 @@
measurable: Measurable,
constraints: Constraints
): MeasureResult {
+
val horizontal = start.roundToPx() + end.roundToPx()
val vertical = top.roundToPx() + bottom.roundToPx()
@@ -244,28 +391,43 @@
}
}
-/**
- * Describes a padding to be applied along the edges inside a box.
- */
-@Immutable
-data class PaddingValues(
- @Stable
- val start: Dp = 0.dp,
- @Stable
- val top: Dp = 0.dp,
- @Stable
- val end: Dp = 0.dp,
- @Stable
- val bottom: Dp = 0.dp
-) {
- /**
- * Describes a padding of [all] dp along all 4 edges.
- */
- constructor(all: Dp) : this(all, all, all, all)
+private class PaddingValuesModifier(
+ val paddingValues: PaddingValues,
+ inspectorInfo: InspectorInfo.() -> Unit
+) : LayoutModifier, InspectorValueInfo(inspectorInfo) {
+ override fun MeasureScope.measure(
+ measurable: Measurable,
+ constraints: Constraints
+ ): MeasureResult {
+ require(
+ paddingValues.calculateLeftPadding(LayoutDirection.Ltr) >= 0.dp &&
+ paddingValues.calculateTopPadding() >= 0.dp &&
+ paddingValues.calculateRightPadding(LayoutDirection.Ltr) >= 0.dp &&
+ paddingValues.calculateBottomPadding() >= 0.dp
+ ) {
+ "Padding must be non-negative"
+ }
+ val horizontal = paddingValues.calculateLeftPadding(LayoutDirection.Ltr).roundToPx() +
+ paddingValues.calculateRightPadding(layoutDirection).roundToPx()
+ val vertical = paddingValues.calculateTopPadding().roundToPx() +
+ paddingValues.calculateBottomPadding().roundToPx()
- /**
- * Describes a padding of [horizontal] dp along the left and right edges, and of [vertical]
- * dp along the top and bottom edges.
- */
- constructor(horizontal: Dp, vertical: Dp) : this(horizontal, vertical, horizontal, vertical)
+ val placeable = measurable.measure(constraints.offset(-horizontal, -vertical))
+
+ val width = constraints.constrainWidth(placeable.width + horizontal)
+ val height = constraints.constrainHeight(placeable.height + vertical)
+ return layout(width, height) {
+ placeable.place(
+ paddingValues.calculateLeftPadding(layoutDirection).roundToPx(),
+ paddingValues.calculateTopPadding().roundToPx()
+ )
+ }
+ }
+
+ override fun hashCode() = paddingValues.hashCode()
+
+ override fun equals(other: Any?): Boolean {
+ val otherModifier = other as? PaddingValuesModifier ?: return false
+ return paddingValues == otherModifier.paddingValues
+ }
}
diff --git a/compose/foundation/foundation/api/current.txt b/compose/foundation/foundation/api/current.txt
index 26bf9f0..4315ed5 100644
--- a/compose/foundation/foundation/api/current.txt
+++ b/compose/foundation/foundation/api/current.txt
@@ -517,8 +517,10 @@
}
public final class BasicTextFieldKt {
- method @androidx.compose.runtime.Composable public static void BasicTextField-Q80SffI(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
- method @androidx.compose.runtime.Composable public static void BasicTextField-qDYpSg4(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
+ method @androidx.compose.runtime.Composable public static void BasicTextField-4ZnogcI(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
+ method @androidx.compose.runtime.Composable public static void BasicTextField-IrUQABg(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
+ method @Deprecated @androidx.compose.runtime.Composable public static void BasicTextField-Q80SffI(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
+ method @Deprecated @androidx.compose.runtime.Composable public static void BasicTextField-qDYpSg4(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
}
public final class BasicTextKt {
diff --git a/compose/foundation/foundation/api/public_plus_experimental_current.txt b/compose/foundation/foundation/api/public_plus_experimental_current.txt
index 26bf9f0..4315ed5 100644
--- a/compose/foundation/foundation/api/public_plus_experimental_current.txt
+++ b/compose/foundation/foundation/api/public_plus_experimental_current.txt
@@ -517,8 +517,10 @@
}
public final class BasicTextFieldKt {
- method @androidx.compose.runtime.Composable public static void BasicTextField-Q80SffI(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
- method @androidx.compose.runtime.Composable public static void BasicTextField-qDYpSg4(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
+ method @androidx.compose.runtime.Composable public static void BasicTextField-4ZnogcI(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
+ method @androidx.compose.runtime.Composable public static void BasicTextField-IrUQABg(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
+ method @Deprecated @androidx.compose.runtime.Composable public static void BasicTextField-Q80SffI(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
+ method @Deprecated @androidx.compose.runtime.Composable public static void BasicTextField-qDYpSg4(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
}
public final class BasicTextKt {
diff --git a/compose/foundation/foundation/api/restricted_current.txt b/compose/foundation/foundation/api/restricted_current.txt
index 26bf9f0..4315ed5 100644
--- a/compose/foundation/foundation/api/restricted_current.txt
+++ b/compose/foundation/foundation/api/restricted_current.txt
@@ -517,8 +517,10 @@
}
public final class BasicTextFieldKt {
- method @androidx.compose.runtime.Composable public static void BasicTextField-Q80SffI(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
- method @androidx.compose.runtime.Composable public static void BasicTextField-qDYpSg4(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
+ method @androidx.compose.runtime.Composable public static void BasicTextField-4ZnogcI(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
+ method @androidx.compose.runtime.Composable public static void BasicTextField-IrUQABg(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
+ method @Deprecated @androidx.compose.runtime.Composable public static void BasicTextField-Q80SffI(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
+ method @Deprecated @androidx.compose.runtime.Composable public static void BasicTextField-qDYpSg4(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long cursorColor, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
}
public final class BasicTextKt {
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/CapitalizationAutoCorrectDemo.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/CapitalizationAutoCorrectDemo.kt
index ae9ddb2..9d3b084 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/CapitalizationAutoCorrectDemo.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/CapitalizationAutoCorrectDemo.kt
@@ -20,6 +20,8 @@
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.foundation.text.KeyboardActionScope
+import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
@@ -96,16 +98,23 @@
val state = rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(TextFieldValue())
}
+ val anyAction: KeyboardActionScope.() -> Unit = { controller.value?.hideSoftwareKeyboard() }
BasicTextField(
modifier = demoTextFieldModifiers.defaultMinSizeConstraints(100.dp),
value = state.value,
keyboardOptions = data.keyboardOptions,
+ // TODO(b/179226323): Add API to set the same KeyboardAction lambda for all ImeActions.
+ keyboardActions = KeyboardActions(
+ onDone = anyAction,
+ onGo = anyAction,
+ onNext = anyAction,
+ onPrevious = anyAction,
+ onSearch = anyAction,
+ onSend = anyAction,
+ ),
onValueChange = { state.value = it },
textStyle = TextStyle(fontSize = fontSize8),
onTextInputStarted = { controller.value = it },
- onImeActionPerformed = {
- controller.value?.hideSoftwareKeyboard()
- },
cursorColor = Color.Red
)
}
\ No newline at end of file
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeInputField.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeInputField.kt
index ba0fbbd..43016bb0 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeInputField.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeInputField.kt
@@ -23,6 +23,8 @@
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.foundation.text.KeyboardActionScope
+import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Providers
@@ -82,6 +84,7 @@
) {
val controller = remember { mutableStateOf<SoftwareKeyboardController?>(null) }
val state = rememberSaveable { mutableStateOf(text) }
+ val anyAction: KeyboardActionScope.() -> Unit = { controller.value?.hideSoftwareKeyboard() }
BasicTextField(
modifier = demoTextFieldModifiers,
value = state.value,
@@ -90,12 +93,18 @@
keyboardType = keyboardType,
imeAction = imeAction
),
+ // TODO(b/179226323): Add API to set the same KeyboardAction lambda for all ImeActions.
+ keyboardActions = KeyboardActions(
+ onDone = anyAction,
+ onGo = anyAction,
+ onNext = anyAction,
+ onPrevious = anyAction,
+ onSearch = anyAction,
+ onSend = anyAction,
+ ),
onValueChange = { state.value = it },
textStyle = TextStyle(fontSize = fontSize8),
onTextInputStarted = { controller.value = it },
- onImeActionPerformed = {
- controller.value?.hideSoftwareKeyboard()
- }
)
}
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/KeyboardSingleLineDemo.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/KeyboardSingleLineDemo.kt
index 1bc5c66..d012f01 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/KeyboardSingleLineDemo.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/KeyboardSingleLineDemo.kt
@@ -20,6 +20,8 @@
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.foundation.text.KeyboardActionScope
+import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
@@ -127,17 +129,24 @@
val state = rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(TextFieldValue())
}
+ val anyAction: KeyboardActionScope.() -> Unit = { controller.value?.hideSoftwareKeyboard() }
BasicTextField(
modifier = demoTextFieldModifiers.defaultMinSizeConstraints(100.dp),
value = state.value,
keyboardOptions = data.keyboardOptions,
+ // TODO(b/179226323): Add API to set the same KeyboardAction lambda for all ImeActions.
+ keyboardActions = KeyboardActions(
+ onDone = anyAction,
+ onGo = anyAction,
+ onNext = anyAction,
+ onPrevious = anyAction,
+ onSearch = anyAction,
+ onSend = anyAction,
+ ),
singleLine = data.singleLine,
onValueChange = { state.value = it },
textStyle = TextStyle(fontSize = fontSize8),
onTextInputStarted = { controller.value = it },
- onImeActionPerformed = {
- controller.value?.hideSoftwareKeyboard()
- },
cursorColor = Color.Red
)
}
\ No newline at end of file
diff --git a/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/ImageSamples.kt b/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/ImageSamples.kt
index 94338b0..ba2d1d9 100644
--- a/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/ImageSamples.kt
+++ b/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/ImageSamples.kt
@@ -29,7 +29,7 @@
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.Paint
import androidx.compose.ui.graphics.drawscope.DrawScope
-import androidx.compose.ui.graphics.painter.ImagePainter
+import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
@@ -45,11 +45,11 @@
@Sampled
@Composable
-fun ImagePainterSubsectionSample() {
+fun BitmapPainterSubsectionSample() {
val ImageBitmap = createTestImage()
// Lays out and draws an image sized to the rectangular subsection of the ImageBitmap
Image(
- painter = ImagePainter(
+ painter = BitmapPainter(
ImageBitmap,
IntOffset(10, 12),
IntSize(50, 60)
@@ -60,7 +60,7 @@
@Sampled
@Composable
-fun ImagePainterSample() {
+fun BitmapPainterSample() {
val customPainter = remember {
object : Painter() {
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ImageTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ImageTest.kt
index 3f88818..ec15702 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ImageTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ImageTest.kt
@@ -41,7 +41,7 @@
import androidx.compose.ui.graphics.asAndroidBitmap
import androidx.compose.ui.graphics.drawscope.CanvasDrawScope
import androidx.compose.ui.graphics.painter.ColorPainter
-import androidx.compose.ui.graphics.painter.ImagePainter
+import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalDensity
@@ -162,7 +162,7 @@
.wrapContentSize(Alignment.Center)
) {
Image(
- ImagePainter(
+ BitmapPainter(
createImageBitmap(),
IntOffset(
imageWidth / 2 - subsectionWidth / 2,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Image.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Image.kt
index 338de01..943b3ad 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Image.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Image.kt
@@ -27,7 +27,7 @@
import androidx.compose.ui.graphics.DefaultAlpha
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.painter.ColorPainter
-import androidx.compose.ui.graphics.painter.ImagePainter
+import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
@@ -50,7 +50,7 @@
*
* For use cases that require drawing a rectangular subset of the [ImageBitmap] consumers can use
* overload that consumes a [Painter] parameter shown in this sample
- * @sample androidx.compose.foundation.samples.ImagePainterSubsectionSample
+ * @sample androidx.compose.foundation.samples.BitmapPainterSubsectionSample
*
* @param bitmap The [ImageBitmap] to draw
* @param contentDescription text used by accessibility services to describe what this image
@@ -78,9 +78,9 @@
alpha: Float = DefaultAlpha,
colorFilter: ColorFilter? = null
) {
- val imagePainter = remember(bitmap) { ImagePainter(bitmap) }
+ val bitmapPainter = remember(bitmap) { BitmapPainter(bitmap) }
Image(
- painter = imagePainter,
+ painter = bitmapPainter,
contentDescription = contentDescription,
modifier = modifier,
alignment = alignment,
@@ -142,7 +142,7 @@
* of zero and will not draw any content. This can happen for Painter implementations that
* always attempt to fill the bounds like [ColorPainter]
*
- * @sample androidx.compose.foundation.samples.ImagePainterSample
+ * @sample androidx.compose.foundation.samples.BitmapPainterSample
*
* @param painter to draw
* @param contentDescription text used by accessibility services to describe what this image
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt
index 101d319..ea53234 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt
@@ -20,6 +20,8 @@
import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.calculateEndPadding
+import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
@@ -73,8 +75,6 @@
val cachingItemContentFactory = remember { CachingItemContentFactory(restorableItemContent) }
cachingItemContentFactory.itemContentFactory = restorableItemContent
- val startContentPadding = if (isVertical) contentPadding.top else contentPadding.start
- val endContentPadding = if (isVertical) contentPadding.bottom else contentPadding.end
SubcomposeLayout(
modifier
.scrollable(
@@ -91,8 +91,16 @@
// this will update the scope object if the constrains have been changed
cachingItemContentFactory.updateItemScope(this, constraints)
- val startContentPaddingPx = startContentPadding.roundToPx()
- val endContentPaddingPx = endContentPadding.roundToPx()
+ val startContentPadding = if (isVertical) {
+ contentPadding.calculateTopPadding()
+ } else {
+ contentPadding.calculateStartPadding(layoutDirection)
+ }.roundToPx()
+ val endContentPadding = if (isVertical) {
+ contentPadding.calculateBottomPadding()
+ } else {
+ contentPadding.calculateEndPadding(layoutDirection)
+ }.roundToPx()
val mainAxisMaxSize = (if (isVertical) constraints.maxHeight else constraints.maxWidth)
val spaceBetweenItemsDp = if (isVertical) {
requireNotNull(verticalArrangement).spacing
@@ -117,8 +125,8 @@
horizontalAlignment = horizontalAlignment,
verticalAlignment = verticalAlignment,
layoutDirection = layoutDirection,
- startContentPadding = startContentPaddingPx,
- endContentPadding = endContentPaddingPx,
+ startContentPadding = startContentPadding,
+ endContentPadding = endContentPadding,
spacing = spacing,
key = key
)
@@ -128,8 +136,8 @@
itemsCount,
itemProvider,
mainAxisMaxSize,
- startContentPaddingPx,
- endContentPaddingPx,
+ startContentPadding,
+ endContentPadding,
state.firstVisibleItemIndexNonObservable,
state.firstVisibleItemScrollOffsetNonObservable,
state.scrollToBeConsumed
@@ -138,7 +146,7 @@
state.applyMeasureResult(measureResult)
val headers = if (headerIndexes.isNotEmpty()) {
- LazyListHeaders(itemProvider, headerIndexes, measureResult, startContentPaddingPx)
+ LazyListHeaders(itemProvider, headerIndexes, measureResult, startContentPadding)
} else {
null
}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/BasicTextField.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/BasicTextField.kt
index de0fc88..9e6fe14 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/BasicTextField.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/BasicTextField.kt
@@ -83,6 +83,133 @@
* @param textStyle Style configuration that applies at character level such as color, font etc.
* @param keyboardOptions software keyboard options that contains configuration such as
* [KeyboardType] and [ImeAction].
+ * @param keyboardActions when the input service emits an IME action, the corresponding callback
+ * is called. Note that this IME action may be different from what you specified in
+ * [KeyboardOptions.imeAction].
+ * @param singleLine when set to true, this text field becomes a single horizontally scrolling
+ * text field instead of wrapping onto multiple lines. The keyboard will be informed to not show
+ * the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the
+ * maxLines attribute will be automatically set to 1.
+ * @param maxLines the maximum height in terms of maximum number of visible lines. Should be
+ * equal or greater than 1. Note that this parameter will be ignored and instead maxLines will be
+ * set to 1 if [singleLine] is set to true.
+ * @param visualTransformation The visual transformation filter for changing the visual
+ * representation of the input. By default no visual transformation is applied.
+ * @param onTextLayout Callback that is executed when a new text layout is calculated.
+ * @param onTextInputStarted Callback that is executed when the initialization has done for
+ * communicating with platform text input service, e.g. software keyboard on Android. Called with
+ * [SoftwareKeyboardController] instance which can be used for requesting input show/hide software
+ * keyboard.
+ * @param interactionState the [InteractionState] representing the different [Interaction]s
+ * present on this TextField. You can create and pass in your own remembered [InteractionState]
+ * if you want to read the [InteractionState] and customize the appearance / behavior of this
+ * TextField in different [Interaction]s.
+ * @param cursorColor Color of the cursor. If [Color.Unspecified], there will be no cursor drawn
+ * @param decorationBox Composable lambda that allows to add decorations around text field, such
+ * as icon, placeholder, helper messages or similar, and automatically increase the hit target area
+ * of the text field. To allow you to control the placement of the inner text field relative to your
+ * decorations, the text field implementation will pass in a framework-controlled composable
+ * parameter "innerTextField" to the decorationBox lambda you provide. You must call
+ * innerTextField exactly once.
+ */
+@Composable
+fun BasicTextField(
+ value: String,
+ onValueChange: (String) -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ readOnly: Boolean = false,
+ textStyle: TextStyle = TextStyle.Default,
+ keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
+ keyboardActions: KeyboardActions = KeyboardActions.Default,
+ singleLine: Boolean = false,
+ maxLines: Int = Int.MAX_VALUE,
+ visualTransformation: VisualTransformation = VisualTransformation.None,
+ onTextLayout: (TextLayoutResult) -> Unit = {},
+ onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
+ interactionState: InteractionState = remember { InteractionState() },
+ cursorColor: Color = Color.Black,
+ decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit =
+ @Composable { innerTextField -> innerTextField() }
+) {
+ var textFieldValueState by remember { mutableStateOf(TextFieldValue(text = value)) }
+ val textFieldValue = textFieldValueState.copy(text = value)
+
+ BasicTextField(
+ value = textFieldValue,
+ onValueChange = {
+ textFieldValueState = it
+ if (value != it.text) {
+ onValueChange(it.text)
+ }
+ },
+ modifier = modifier,
+ enabled = enabled,
+ readOnly = readOnly,
+ textStyle = textStyle,
+ keyboardOptions = keyboardOptions,
+ keyboardActions = keyboardActions,
+ maxLines = maxLines,
+ visualTransformation = visualTransformation,
+ onTextLayout = onTextLayout,
+ onTextInputStarted = onTextInputStarted,
+ cursorColor = cursorColor,
+ interactionState = interactionState,
+ singleLine = singleLine,
+ decorationBox = decorationBox
+ )
+}
+
+// TODO(b/178633932): Remove after Alpha 12.
+/**
+ * Basic composable that enables users to edit text via hardware or software keyboard, but
+ * provides no decorations like hint or placeholder.
+ *
+ * Whenever the user edits the text, [onValueChange] is called with the most up to date state
+ * represented by [String] with which developer is expected to update their state.
+ *
+ * Unlike [TextFieldValue] overload, this composable does not let the developer to control
+ * selection, cursor and text composition information. Please check [TextFieldValue] and
+ * corresponding [BasicTextField] overload for more information.
+ *
+ * It is crucial that the value provided in the [onValueChange] is fed back into [BasicTextField] in
+ * order to have the final state of the text being displayed.
+ *
+ * Example usage:
+ * @sample androidx.compose.foundation.samples.BasicTextFieldWithStringSample
+ *
+ * Please keep in mind that [onValueChange] is useful to be informed about the latest state of the
+ * text input by users, however it is generally not recommended to modify the value that you get
+ * via [onValueChange] callback. Any change to this value may result in a context reset and end
+ * up with input session restart. Such a scenario would cause glitches in the UI or text input
+ * experience for users.
+ *
+ * This composable provides basic text editing functionality, however does not include any
+ * decorations such as borders, hints/placeholder. A design system based implementation such as
+ * Material Design Filled text field is typically what is needed to cover most of the needs. This
+ * composable is designed to be used when a custom implementation for different design system is
+ * needed.
+ *
+ * For example, if you need to include a placeholder in your TextField, you can write a composable
+ * using the decoration box like this:
+ * @sample androidx.compose.foundation.samples.PlaceholderBasicTextFieldSample
+ *
+ * If you want to add decorations to your text field, such as icon or similar, and increase the
+ * hit target area, use the decoration box:
+ * @sample androidx.compose.foundation.samples.TextFieldWithIconSample
+ *
+ * @param value the input [String] text to be shown in the text field
+ * @param onValueChange the callback that is triggered when the input service updates the text. An
+ * updated text comes as a parameter of the callback
+ * @param modifier optional [Modifier] for this text field.
+ * @param enabled controls the enabled state of the [BasicTextField]. When `false`, the text
+ * field will be neither editable nor focusable, the input of the text field will not be selectable
+ * @param readOnly controls the editable state of the [BasicTextField]. When `true`, the text
+ * field can not be modified, however, a user can focus it and copy text from it. Read-only text
+ * fields are usually used to display pre-filled forms that user can not edit
+ * @param textStyle Style configuration that applies at character level such as color, font etc.
+ * @param keyboardOptions software keyboard options that contains configuration such as
+ * [KeyboardType] and [ImeAction].
* @param singleLine when set to true, this text field becomes a single horizontally scrolling
* text field instead of wrapping onto multiple lines. The keyboard will be informed to not show
* the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the
@@ -112,6 +239,42 @@
* parameter "innerTextField" to the decorationBox lambda you provide. You must call
* innerTextField exactly once.
*/
+@Suppress("UNUSED_PARAMETER")
+@Deprecated(
+ message = "Instead of onImeActionPerformed, use the keyboardActions parameter to specify " +
+ "IMEAction callbacks.",
+ replaceWith = ReplaceWith(
+ expression = """BasicTextField(
+ value,
+ onValueChange,
+ modifier,
+ enabled,
+ readOnly,
+ textStyle,
+ keyboardOptions,
+ KeyboardActions(
+ onDone= { onImeActionPerformed },
+ onGo = { onImeActionPerformed },
+ onNext= { onImeActionPerformed },
+ onPrevious= { onImeActionPerformed },
+ onSearch = { onImeActionPerformed },
+ onSend = { onImeActionPerformed }
+ ),
+ singleLine,
+ maxLines,
+ visualTransformation,
+ onTextLayout,
+ onTextInputStarted,
+ interactionState,
+ cursorColor,
+ decorationBox)""",
+ imports = [
+ "androidx.compose.foundation.text.KeyboardActions",
+ "androidx.compose.foundation.text.BasicTextField"
+ ]
+ ),
+ level = DeprecationLevel.ERROR
+)
@Composable
fun BasicTextField(
value: String,
@@ -123,7 +286,106 @@
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
singleLine: Boolean = false,
maxLines: Int = Int.MAX_VALUE,
- onImeActionPerformed: (ImeAction) -> Unit = {},
+ onImeActionPerformed: (ImeAction) -> Unit,
+ visualTransformation: VisualTransformation = VisualTransformation.None,
+ onTextLayout: (TextLayoutResult) -> Unit = {},
+ onTextInputStarted: (SoftwareKeyboardController) -> Unit,
+ interactionState: InteractionState = remember { InteractionState() },
+ cursorColor: Color = Color.Black,
+ decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit =
+ @Composable { innerTextField -> innerTextField() }
+) = Unit
+
+/**
+ * Basic composable that enables users to edit text via hardware or software keyboard, but
+ * provides no decorations like hint or placeholder.
+ *
+ * Whenever the user edits the text, [onValueChange] is called with the most up to date state
+ * represented by [TextFieldValue]. [TextFieldValue] contains the text entered by user, as well
+ * as selection, cursor and text composition information. Please check [TextFieldValue] for the
+ * description of its contents.
+ *
+ * It is crucial that the value provided in the [onValueChange] is fed back into [BasicTextField] in
+ * order to have the final state of the text being displayed.
+ *
+ * Example usage:
+ * @sample androidx.compose.foundation.samples.BasicTextFieldSample
+ *
+ * Please keep in mind that [onValueChange] is useful to be informed about the latest state of the
+ * text input by users, however it is generally not recommended to modify the values in the
+ * [TextFieldValue] that you get via [onValueChange] callback. Any change to the values in
+ * [TextFieldValue] may result in a context reset and end up with input session restart. Such
+ * a scenario would cause glitches in the UI or text input experience for users.
+ *
+ * This composable provides basic text editing functionality, however does not include any
+ * decorations such as borders, hints/placeholder. A design system based implementation such as
+ * Material Design Filled text field is typically what is needed to cover most of the needs. This
+ * composable is designed to be used when a custom implementation for different design system is
+ * needed.
+ *
+ * For example, if you need to include a placeholder in your TextField, you can write a composable
+ * using the decoration box like this:
+ * @sample androidx.compose.foundation.samples.PlaceholderBasicTextFieldSample
+ *
+ *
+ * If you want to add decorations to your text field, such as icon or similar, and increase the
+ * hit target area, use the decoration box:
+ * @sample androidx.compose.foundation.samples.TextFieldWithIconSample
+ *
+ * @param value The [androidx.compose.ui.text.input.TextFieldValue] to be shown in the
+ * [BasicTextField].
+ * @param onValueChange Called when the input service updates the values in [TextFieldValue].
+ * @param modifier optional [Modifier] for this text field.
+ * @param enabled controls the enabled state of the [BasicTextField]. When `false`, the text
+ * field will be neither editable nor focusable, the input of the text field will not be selectable
+ * @param readOnly controls the editable state of the [BasicTextField]. When `true`, the text
+ * field can not be modified, however, a user can focus it and copy text from it. Read-only text
+ * fields are usually used to display pre-filled forms that user can not edit
+ * @param textStyle Style configuration that applies at character level such as color, font etc.
+ * @param keyboardOptions software keyboard options that contains configuration such as
+ * [KeyboardType] and [ImeAction].
+ * @param keyboardActions when the input service emits an IME action, the corresponding callback
+ * is called. Note that this IME action may be different from what you specified in
+ * [KeyboardOptions.imeAction].
+ * @param singleLine when set to true, this text field becomes a single horizontally scrolling
+ * text field instead of wrapping onto multiple lines. The keyboard will be informed to not show
+ * the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the
+ * maxLines attribute will be automatically set to 1.
+ * @param maxLines the maximum height in terms of maximum number of visible lines. Should be
+ * equal or greater than 1. Note that this parameter will be ignored and instead maxLines will be
+ * set to 1 if [singleLine] is set to true.
+ * @param visualTransformation The visual transformation filter for changing the visual
+ * representation of the input. By default no visual transformation is applied.
+ * @param onTextLayout Callback that is executed when a new text layout is calculated.
+ * @param onTextInputStarted Callback that is executed when the initialization has done for
+ * communicating with platform text input service, e.g. software keyboard on Android. Called with
+ * [SoftwareKeyboardController] instance which can be used for requesting input show/hide software
+ * keyboard.
+ * @param interactionState The [InteractionState] representing the different [Interaction]s
+ * present on this TextField. You can create and pass in your own remembered [InteractionState]
+ * if you want to read the [InteractionState] and customize the appearance / behavior of this
+ * TextField in different [Interaction]s.
+ * @param cursorColor Color of the cursor. If [Color.Unspecified], there will be no cursor drawn
+ * @param decorationBox Composable lambda that allows to add decorations around text field, such
+ * as icon, placeholder, helper messages or similar, and automatically increase the hit target area
+ * of the text field. To allow you to control the placement of the inner text field relative to your
+ * decorations, the text field implementation will pass in a framework-controlled composable
+ * parameter "innerTextField" to the decorationBox lambda you provide. You must call
+ * innerTextField exactly once.
+ */
+@Composable
+@OptIn(InternalTextApi::class)
+fun BasicTextField(
+ value: TextFieldValue,
+ onValueChange: (TextFieldValue) -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ readOnly: Boolean = false,
+ textStyle: TextStyle = TextStyle.Default,
+ keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
+ keyboardActions: KeyboardActions = KeyboardActions.Default,
+ singleLine: Boolean = false,
+ maxLines: Int = Int.MAX_VALUE,
visualTransformation: VisualTransformation = VisualTransformation.None,
onTextLayout: (TextLayoutResult) -> Unit = {},
onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
@@ -132,34 +394,27 @@
decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit =
@Composable { innerTextField -> innerTextField() }
) {
- var textFieldValueState by remember { mutableStateOf(TextFieldValue(text = value)) }
- val textFieldValue = textFieldValueState.copy(text = value)
-
- BasicTextField(
- value = textFieldValue,
- onValueChange = {
- textFieldValueState = it
- if (value != it.text) {
- onValueChange(it.text)
- }
- },
+ CoreTextField(
+ value = value,
+ onValueChange = onValueChange,
modifier = modifier,
- enabled = enabled,
- readOnly = readOnly,
textStyle = textStyle,
- keyboardOptions = keyboardOptions,
- maxLines = maxLines,
- onImeActionPerformed = onImeActionPerformed,
visualTransformation = visualTransformation,
onTextLayout = onTextLayout,
+ interactionState = interactionState,
onTextInputStarted = onTextInputStarted,
cursorColor = cursorColor,
- interactionState = interactionState,
- singleLine = singleLine,
- decorationBox = decorationBox
+ imeOptions = keyboardOptions.toImeOptions(singleLine = singleLine),
+ keyboardActions = keyboardActions,
+ softWrap = !singleLine,
+ maxLines = if (singleLine) 1 else maxLines,
+ decorationBox = decorationBox,
+ enabled = enabled,
+ readOnly = readOnly
)
}
+// TODO(b/178633932): Remove after Alpha 12.
/**
* Basic composable that enables users to edit text via hardware or software keyboard, but
* provides no decorations like hint or placeholder.
@@ -237,6 +492,43 @@
* parameter "innerTextField" to the decorationBox lambda you provide. You must call
* innerTextField exactly once.
*/
+@Suppress("UNUSED_PARAMETER")
+@Deprecated(
+ message = "Instead of onImeActionPerformed, use the keyboardActions parameter to specify " +
+ "IMEAction callbacks.",
+ replaceWith = ReplaceWith(
+ expression = """BasicTextField(
+ value,
+ onValueChange,
+ modifier,
+ enabled,
+ readOnly,
+ textStyle,
+ keyboardOptions,
+ KeyboardActions(
+ onDone= { onImeActionPerformed },
+ onGo = { onImeActionPerformed },
+ onNext= { onImeActionPerformed },
+ onPrevious= { onImeActionPerformed },
+ onSearch = { onImeActionPerformed },
+ onSend = { onImeActionPerformed }
+ ),
+ singleLine,
+ maxLines,
+ visualTransformation,
+ onTextLayout,
+ onTextInputStarted,
+ interactionState,
+ cursorColor,
+ decorationBox
+ )""",
+ imports = [
+ "androidx.compose.foundation.text.KeyboardActions",
+ "androidx.compose.foundation.text.BasicTextField"
+ ]
+ ),
+ level = DeprecationLevel.ERROR
+)
@Composable
@OptIn(InternalTextApi::class)
fun BasicTextField(
@@ -249,7 +541,7 @@
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
singleLine: Boolean = false,
maxLines: Int = Int.MAX_VALUE,
- onImeActionPerformed: (ImeAction) -> Unit = {},
+ onImeActionPerformed: (ImeAction) -> Unit,
visualTransformation: VisualTransformation = VisualTransformation.None,
onTextLayout: (TextLayoutResult) -> Unit = {},
onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
@@ -257,23 +549,4 @@
cursorColor: Color = Color.Black,
decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit =
@Composable { innerTextField -> innerTextField() }
-) {
- CoreTextField(
- value = value,
- onValueChange = onValueChange,
- modifier = modifier,
- textStyle = textStyle,
- onImeActionPerformed = onImeActionPerformed,
- visualTransformation = visualTransformation,
- onTextLayout = onTextLayout,
- interactionState = interactionState,
- onTextInputStarted = onTextInputStarted,
- cursorColor = cursorColor,
- imeOptions = keyboardOptions.toImeOptions(singleLine = singleLine),
- softWrap = !singleLine,
- maxLines = if (singleLine) 1 else maxLines,
- decorationBox = decorationBox,
- enabled = enabled,
- readOnly = readOnly
- )
-}
\ No newline at end of file
+) = Unit
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
index b6f9e71..94eb804 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
@@ -142,7 +142,7 @@
* @param maxLines The maximum height in terms of maximum number of visible lines. Should be
* equal or greater than 1.
* @param imeOptions Contains different IME configuration options.
- * @param keyboardActions When the input service emits an IME action, the corresponding callback
+ * @param keyboardActions when the input service emits an IME action, the corresponding callback
* is called. Note that this IME action may be different from what you specified in
* [KeyboardOptions.imeAction].
* @param enabled controls the enabled state of the text field. When `false`, the text
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.kt
index 9f3f449..868f62b 100644
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.kt
+++ b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.kt
@@ -191,7 +191,7 @@
SliderAdapter(adapter, containerSize, minimalHeight)
}
- val scrollThickness = style.thickness.toIntPx()
+ val scrollThickness = style.thickness.roundToPx()
val measureBlocks = if (isVertical) {
remember(sliderAdapter, scrollThickness) {
verticalMeasureBlocks(sliderAdapter, { containerSize = it }, scrollThickness)
diff --git a/compose/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/SpacingBenchmark.kt b/compose/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/SpacingBenchmark.kt
index 4ae98d7..5eae5b2 100644
--- a/compose/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/SpacingBenchmark.kt
+++ b/compose/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/SpacingBenchmark.kt
@@ -17,6 +17,8 @@
package androidx.ui.benchmark.test
import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.calculateEndPadding
+import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
@@ -238,10 +240,10 @@
if (measurable == null) {
layout(constraints.minWidth, constraints.minHeight) { }
} else {
- val paddingLeft = padding.start.roundToPx()
- val paddingTop = padding.top.roundToPx()
- val paddingRight = padding.end.roundToPx()
- val paddingBottom = padding.bottom.roundToPx()
+ val paddingLeft = padding.calculateStartPadding(layoutDirection).roundToPx()
+ val paddingTop = padding.calculateTopPadding().roundToPx()
+ val paddingRight = padding.calculateEndPadding(layoutDirection).roundToPx()
+ val paddingBottom = padding.calculateBottomPadding().roundToPx()
val horizontalPadding = (paddingLeft + paddingRight)
val verticalPadding = (paddingTop + paddingBottom)
diff --git a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt
index e5d7d45..d60c8fc 100644
--- a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt
+++ b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt
@@ -30,6 +30,7 @@
import androidx.compose.integration.demos.common.Demo
import androidx.compose.integration.demos.common.DemoCategory
import androidx.compose.integration.demos.common.allLaunchableDemos
+import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.ListItem
@@ -125,6 +126,7 @@
}
@Composable
+@OptIn(ExperimentalMaterialApi::class)
private fun DisplayDemoCategory(category: DemoCategory, onNavigate: (Demo) -> Unit) {
// TODO: migrate to LazyColumn after b/175671850
Column(Modifier.verticalScroll(rememberScrollState())) {
diff --git a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt
index 4e37cde..453b308 100644
--- a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt
+++ b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt
@@ -26,6 +26,7 @@
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.verticalScroll
import androidx.compose.integration.demos.common.Demo
+import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.ListItem
@@ -128,6 +129,7 @@
* [ListItem] that displays a [demo] and highlights any matches for [filterText] inside [Demo.title]
*/
@Composable
+@OptIn(ExperimentalMaterialApi::class)
private fun FilteredDemoListItem(
demo: Demo,
filterText: String,
diff --git a/compose/integration-tests/docs-snippets/build.gradle b/compose/integration-tests/docs-snippets/build.gradle
index 68bb102..8259db5 100644
--- a/compose/integration-tests/docs-snippets/build.gradle
+++ b/compose/integration-tests/docs-snippets/build.gradle
@@ -40,6 +40,7 @@
implementation project(":compose:ui:ui-viewbinding")
implementation project(":navigation:navigation-compose")
implementation project(":activity:activity-compose")
+ implementation project(":lifecycle:lifecycle-viewmodel-compose")
implementation(KOTLIN_STDLIB)
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/accessibility/Accessibility.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/accessibility/Accessibility.kt
index 24d1957..0f72d12 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/accessibility/Accessibility.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/accessibility/Accessibility.kt
@@ -37,7 +37,7 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ImageBitmap
-import androidx.compose.ui.graphics.painter.ImagePainter
+import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.CustomAccessibilityAction
@@ -72,7 +72,7 @@
@Composable
fun PostImage(post: Post, modifier: Modifier = Modifier) {
val image = if (post.imageThumb != null) {
- ImagePainter(post.imageThumb)
+ BitmapPainter(post.imageThumb)
} else {
painterResource(R.drawable.placeholder)
}
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/Interoperability.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/Interoperability.kt
index 509abfd..ca8e4eb 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/Interoperability.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/Interoperability.kt
@@ -84,9 +84,9 @@
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.compose.ui.viewinterop.AndroidViewBinding
-import androidx.compose.ui.viewinterop.viewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewmodel.compose.viewModel
/**
* This file lets DevRel track changes to snippets present in
@@ -226,7 +226,8 @@
}
}
-@Composable private fun RowScope.InteropSnippet7() {
+@Composable
+private fun RowScope.InteropSnippet7() {
Text(
text = stringResource(R.string.ok),
modifier = Modifier.padding(dimensionResource(R.dimen.padding_small))
@@ -270,6 +271,7 @@
}
}
}
+
/* ktlint-enable indent */
private object InteropSnippet10 {
class ExampleViewModel : ViewModel() { /*...*/ }
@@ -719,21 +721,26 @@
object layout {
const val fragment_example = 1
}
+
object id {
const val compose_view = 2
const val compose_view_x = 3
}
+
object string {
const val ok = 4
const val plane_description = 5
const val login = 6
}
+
object dimen {
const val padding_small = 7
}
+
object drawable {
const val ic_plane = 8
}
+
object color {
const val Blue700 = 9
}
@@ -745,12 +752,15 @@
val coordinator = Coord()
lateinit var myView: View
}
+
private class DataExample(val title: String = "")
+
private val data = DataExample()
private fun startActivity(): Nothing = TODO()
class ExampleViewModel : ViewModel() {
val exampleLiveData = MutableLiveData(" ")
}
+
private fun ShowData(dataExample: State<String?>): Nothing = TODO()
private class ExampleImageLoader {
fun load(url: String): DummyInto = TODO()
@@ -759,21 +769,44 @@
open class Listener {
open fun onSuccess(bitmap: Bitmap): Unit = TODO()
}
+
companion object {
fun get() = ExampleImageLoader()
}
}
+
private class DummyInto {
- fun into(listener: ExampleImageLoader.Listener) { }
+ fun into(listener: ExampleImageLoader.Listener) {}
}
-private fun ExampleComposable() { }
-@Composable private fun MdcTheme(content: @Composable () -> Unit) { }
-@Composable private fun AppCompatTheme(content: @Composable () -> Unit) { }
-@Composable private fun BlueTheme(content: @Composable () -> Unit) { }
-@Composable private fun PinkTheme(content: @Composable () -> Unit) { }
-@Composable private fun YourAppTheme(content: @Composable () -> Unit) { }
-@Composable private fun ProvideWindowInsets(content: @Composable () -> Unit) { }
-@Composable private fun Icon() { }
+
+private fun ExampleComposable() {}
+@Composable
+private fun MdcTheme(content: @Composable () -> Unit) {
+}
+
+@Composable
+private fun AppCompatTheme(content: @Composable () -> Unit) {
+}
+
+@Composable
+private fun BlueTheme(content: @Composable () -> Unit) {
+}
+
+@Composable
+private fun PinkTheme(content: @Composable () -> Unit) {
+}
+
+@Composable
+private fun YourAppTheme(content: @Composable () -> Unit) {
+}
+
+@Composable
+private fun ProvideWindowInsets(content: @Composable () -> Unit) {
+}
+
+@Composable
+private fun Icon() {
+}
private open class Fragment {
@@ -785,15 +818,17 @@
): View {
TODO("not implemented")
}
+
fun requireContext(): Context = TODO()
}
private class AppCompatActivity {
val window: Any = Any()
}
+
private class WindowCompat {
companion object {
- fun setDecorFitsSystemWindows(window: Any, bool: Boolean) { }
+ fun setDecorFitsSystemWindows(window: Any, bool: Boolean) {}
}
}
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt
index f4cafe1..954c142 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt
@@ -49,10 +49,10 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
-import androidx.compose.ui.viewinterop.viewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewmodel.compose.viewModel
/**
* This file lets DevRel track changes to snippets present in
diff --git a/compose/material/material/api/current.txt b/compose/material/material/api/current.txt
index 020730d..213da6a 100644
--- a/compose/material/material/api/current.txt
+++ b/compose/material/material/api/current.txt
@@ -282,7 +282,7 @@
}
public final class DrawerKt {
- method @androidx.compose.runtime.Composable public static void BottomDrawerLayout--6CoO6E(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material.BottomDrawerState drawerState, optional boolean gesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerElevation, optional long drawerBackgroundColor, optional long drawerContentColor, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> bodyContent);
+ method @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Composable public static void BottomDrawerLayout--6CoO6E(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material.BottomDrawerState drawerState, optional boolean gesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerElevation, optional long drawerBackgroundColor, optional long drawerContentColor, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> bodyContent);
method @androidx.compose.runtime.Composable public static void ModalDrawerLayout-TlzqArY(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material.DrawerState drawerState, optional boolean gesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerElevation, optional long drawerBackgroundColor, optional long drawerContentColor, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> bodyContent);
method @androidx.compose.runtime.Composable public static androidx.compose.material.BottomDrawerState rememberBottomDrawerState(androidx.compose.material.BottomDrawerValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material.BottomDrawerValue,java.lang.Boolean> confirmStateChange);
method @androidx.compose.runtime.Composable public static androidx.compose.material.DrawerState rememberDrawerState(androidx.compose.material.DrawerValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material.DrawerValue,java.lang.Boolean> confirmStateChange);
@@ -374,7 +374,7 @@
}
public final class ListItemKt {
- method @androidx.compose.runtime.Composable public static void ListItem(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? secondaryText, optional boolean singleLineSecondaryText, optional kotlin.jvm.functions.Function0<kotlin.Unit>? overlineText, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailing, kotlin.jvm.functions.Function0<kotlin.Unit> text);
+ method @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Composable public static void ListItem(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? secondaryText, optional boolean singleLineSecondaryText, optional kotlin.jvm.functions.Function0<kotlin.Unit>? overlineText, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailing, kotlin.jvm.functions.Function0<kotlin.Unit> text);
}
public final class MaterialTextSelectionColorsKt {
@@ -434,8 +434,10 @@
}
public final class OutlinedTextFieldKt {
- method @androidx.compose.runtime.Composable public static void OutlinedTextField-GDNbQiw(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
- method @androidx.compose.runtime.Composable public static void OutlinedTextField-TM4hwe4(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
+ method @Deprecated @androidx.compose.runtime.Composable public static void OutlinedTextField-GDNbQiw(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
+ method @androidx.compose.runtime.Composable public static void OutlinedTextField-TIQU8E0(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
+ method @Deprecated @androidx.compose.runtime.Composable public static void OutlinedTextField-TM4hwe4(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
+ method @androidx.compose.runtime.Composable public static void OutlinedTextField-uticZRQ(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
}
public final class ProgressIndicatorDefaults {
@@ -690,8 +692,10 @@
}
public final class TextFieldKt {
- method @androidx.compose.runtime.Composable public static void TextField-PrKp87A(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
- method @androidx.compose.runtime.Composable public static void TextField-mP9nhjw(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
+ method @androidx.compose.runtime.Composable public static void TextField-Pd9g5P8(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
+ method @Deprecated @androidx.compose.runtime.Composable public static void TextField-PrKp87A(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
+ method @androidx.compose.runtime.Composable public static void TextField-TG6cP-s(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
+ method @Deprecated @androidx.compose.runtime.Composable public static void TextField-mP9nhjw(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
field public static final float ContainerAlpha = 0.12f;
}
diff --git a/compose/material/material/api/public_plus_experimental_current.txt b/compose/material/material/api/public_plus_experimental_current.txt
index 020730d..213da6a 100644
--- a/compose/material/material/api/public_plus_experimental_current.txt
+++ b/compose/material/material/api/public_plus_experimental_current.txt
@@ -282,7 +282,7 @@
}
public final class DrawerKt {
- method @androidx.compose.runtime.Composable public static void BottomDrawerLayout--6CoO6E(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material.BottomDrawerState drawerState, optional boolean gesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerElevation, optional long drawerBackgroundColor, optional long drawerContentColor, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> bodyContent);
+ method @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Composable public static void BottomDrawerLayout--6CoO6E(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material.BottomDrawerState drawerState, optional boolean gesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerElevation, optional long drawerBackgroundColor, optional long drawerContentColor, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> bodyContent);
method @androidx.compose.runtime.Composable public static void ModalDrawerLayout-TlzqArY(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material.DrawerState drawerState, optional boolean gesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerElevation, optional long drawerBackgroundColor, optional long drawerContentColor, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> bodyContent);
method @androidx.compose.runtime.Composable public static androidx.compose.material.BottomDrawerState rememberBottomDrawerState(androidx.compose.material.BottomDrawerValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material.BottomDrawerValue,java.lang.Boolean> confirmStateChange);
method @androidx.compose.runtime.Composable public static androidx.compose.material.DrawerState rememberDrawerState(androidx.compose.material.DrawerValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material.DrawerValue,java.lang.Boolean> confirmStateChange);
@@ -374,7 +374,7 @@
}
public final class ListItemKt {
- method @androidx.compose.runtime.Composable public static void ListItem(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? secondaryText, optional boolean singleLineSecondaryText, optional kotlin.jvm.functions.Function0<kotlin.Unit>? overlineText, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailing, kotlin.jvm.functions.Function0<kotlin.Unit> text);
+ method @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Composable public static void ListItem(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? secondaryText, optional boolean singleLineSecondaryText, optional kotlin.jvm.functions.Function0<kotlin.Unit>? overlineText, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailing, kotlin.jvm.functions.Function0<kotlin.Unit> text);
}
public final class MaterialTextSelectionColorsKt {
@@ -434,8 +434,10 @@
}
public final class OutlinedTextFieldKt {
- method @androidx.compose.runtime.Composable public static void OutlinedTextField-GDNbQiw(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
- method @androidx.compose.runtime.Composable public static void OutlinedTextField-TM4hwe4(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
+ method @Deprecated @androidx.compose.runtime.Composable public static void OutlinedTextField-GDNbQiw(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
+ method @androidx.compose.runtime.Composable public static void OutlinedTextField-TIQU8E0(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
+ method @Deprecated @androidx.compose.runtime.Composable public static void OutlinedTextField-TM4hwe4(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
+ method @androidx.compose.runtime.Composable public static void OutlinedTextField-uticZRQ(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
}
public final class ProgressIndicatorDefaults {
@@ -690,8 +692,10 @@
}
public final class TextFieldKt {
- method @androidx.compose.runtime.Composable public static void TextField-PrKp87A(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
- method @androidx.compose.runtime.Composable public static void TextField-mP9nhjw(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
+ method @androidx.compose.runtime.Composable public static void TextField-Pd9g5P8(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
+ method @Deprecated @androidx.compose.runtime.Composable public static void TextField-PrKp87A(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
+ method @androidx.compose.runtime.Composable public static void TextField-TG6cP-s(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
+ method @Deprecated @androidx.compose.runtime.Composable public static void TextField-mP9nhjw(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
field public static final float ContainerAlpha = 0.12f;
}
diff --git a/compose/material/material/api/restricted_current.txt b/compose/material/material/api/restricted_current.txt
index 020730d..213da6a 100644
--- a/compose/material/material/api/restricted_current.txt
+++ b/compose/material/material/api/restricted_current.txt
@@ -282,7 +282,7 @@
}
public final class DrawerKt {
- method @androidx.compose.runtime.Composable public static void BottomDrawerLayout--6CoO6E(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material.BottomDrawerState drawerState, optional boolean gesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerElevation, optional long drawerBackgroundColor, optional long drawerContentColor, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> bodyContent);
+ method @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Composable public static void BottomDrawerLayout--6CoO6E(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material.BottomDrawerState drawerState, optional boolean gesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerElevation, optional long drawerBackgroundColor, optional long drawerContentColor, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> bodyContent);
method @androidx.compose.runtime.Composable public static void ModalDrawerLayout-TlzqArY(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material.DrawerState drawerState, optional boolean gesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerElevation, optional long drawerBackgroundColor, optional long drawerContentColor, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> bodyContent);
method @androidx.compose.runtime.Composable public static androidx.compose.material.BottomDrawerState rememberBottomDrawerState(androidx.compose.material.BottomDrawerValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material.BottomDrawerValue,java.lang.Boolean> confirmStateChange);
method @androidx.compose.runtime.Composable public static androidx.compose.material.DrawerState rememberDrawerState(androidx.compose.material.DrawerValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material.DrawerValue,java.lang.Boolean> confirmStateChange);
@@ -374,7 +374,7 @@
}
public final class ListItemKt {
- method @androidx.compose.runtime.Composable public static void ListItem(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? secondaryText, optional boolean singleLineSecondaryText, optional kotlin.jvm.functions.Function0<kotlin.Unit>? overlineText, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailing, kotlin.jvm.functions.Function0<kotlin.Unit> text);
+ method @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Composable public static void ListItem(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? secondaryText, optional boolean singleLineSecondaryText, optional kotlin.jvm.functions.Function0<kotlin.Unit>? overlineText, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailing, kotlin.jvm.functions.Function0<kotlin.Unit> text);
}
public final class MaterialTextSelectionColorsKt {
@@ -434,8 +434,10 @@
}
public final class OutlinedTextFieldKt {
- method @androidx.compose.runtime.Composable public static void OutlinedTextField-GDNbQiw(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
- method @androidx.compose.runtime.Composable public static void OutlinedTextField-TM4hwe4(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
+ method @Deprecated @androidx.compose.runtime.Composable public static void OutlinedTextField-GDNbQiw(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
+ method @androidx.compose.runtime.Composable public static void OutlinedTextField-TIQU8E0(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
+ method @Deprecated @androidx.compose.runtime.Composable public static void OutlinedTextField-TM4hwe4(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
+ method @androidx.compose.runtime.Composable public static void OutlinedTextField-uticZRQ(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor);
}
public final class ProgressIndicatorDefaults {
@@ -690,8 +692,10 @@
}
public final class TextFieldKt {
- method @androidx.compose.runtime.Composable public static void TextField-PrKp87A(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
- method @androidx.compose.runtime.Composable public static void TextField-mP9nhjw(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
+ method @androidx.compose.runtime.Composable public static void TextField-Pd9g5P8(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
+ method @Deprecated @androidx.compose.runtime.Composable public static void TextField-PrKp87A(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
+ method @androidx.compose.runtime.Composable public static void TextField-TG6cP-s(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
+ method @Deprecated @androidx.compose.runtime.Composable public static void TextField-mP9nhjw(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean isErrorValue, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional boolean singleLine, optional int maxLines, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onImeActionPerformed, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional androidx.compose.foundation.InteractionState interactionState, optional long activeColor, optional long inactiveColor, optional long errorColor, optional long backgroundColor, optional androidx.compose.ui.graphics.Shape shape);
field public static final float ContainerAlpha = 0.12f;
}
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/DrawerSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/DrawerSamples.kt
index fd26749..650601e 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/DrawerSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/DrawerSamples.kt
@@ -26,6 +26,7 @@
import androidx.compose.material.BottomDrawerValue
import androidx.compose.material.Button
import androidx.compose.material.DrawerValue
+import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ModalDrawerLayout
import androidx.compose.material.Text
import androidx.compose.material.rememberBottomDrawerState
@@ -65,6 +66,7 @@
@Sampled
@Composable
+@OptIn(ExperimentalMaterialApi::class)
fun BottomDrawerSample() {
val drawerState = rememberBottomDrawerState(BottomDrawerValue.Closed)
BottomDrawerLayout(
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ListSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ListSamples.kt
index 5fefa61..f1a1f11 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ListSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ListSamples.kt
@@ -40,8 +40,8 @@
import androidx.compose.ui.unit.dp
@Sampled
-@OptIn(ExperimentalMaterialApi::class)
@Composable
+@OptIn(ExperimentalMaterialApi::class)
fun ClickableListItems() {
Column {
var switched by remember { mutableStateOf(false) }
@@ -89,6 +89,7 @@
@Sampled
@Composable
+@OptIn(ExperimentalMaterialApi::class)
fun OneLineListItems() {
Column {
ListItem(text = { Text("One line list item with no icon") })
@@ -169,6 +170,7 @@
@Sampled
@Composable
+@OptIn(ExperimentalMaterialApi::class)
fun TwoLineListItems() {
Column {
ListItem(
@@ -222,6 +224,7 @@
@Sampled
@Composable
+@OptIn(ExperimentalMaterialApi::class)
fun ThreeLineListItems() {
Column {
ListItem(
@@ -289,6 +292,7 @@
// Demos for mixing RTL and LTR ListItems:
@Composable
+@OptIn(ExperimentalMaterialApi::class)
fun OneLineRtlLtrListItems() {
Column {
ListItem(text = { Text("One line list item with no icon") })
@@ -328,6 +332,7 @@
}
@Composable
+@OptIn(ExperimentalMaterialApi::class)
fun TwoLineRtlLtrListItems() {
Column {
ListItem(
@@ -375,6 +380,7 @@
}
@Composable
+@OptIn(ExperimentalMaterialApi::class)
fun ThreeLineRtlLtrListItems() {
Column {
ListItem(
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TextFieldSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TextFieldSamples.kt
index 07e7080..324b6bb 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TextFieldSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TextFieldSamples.kt
@@ -19,6 +19,7 @@
import androidx.annotation.Sampled
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.ContentAlpha
import androidx.compose.material.Icon
@@ -35,6 +36,7 @@
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.SoftwareKeyboardController
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
@@ -185,17 +187,18 @@
@Composable
fun TextFieldWithHideKeyboardOnImeAction() {
var text by rememberSaveable { mutableStateOf("") }
-
+ lateinit var softwareKeyboardController: SoftwareKeyboardController
TextField(
value = text,
onValueChange = { text = it },
label = { Text("Label") },
+ onTextInputStarted = { softwareKeyboardController = it },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
- onImeActionPerformed = { action, softwareController ->
- if (action == ImeAction.Done) {
- softwareController?.hideSoftwareKeyboard()
+ keyboardActions = KeyboardActions(
+ onDone = {
+ softwareKeyboardController.hideSoftwareKeyboard()
// do something here
}
- }
+ )
)
-}
\ No newline at end of file
+}
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomSheetScaffoldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomSheetScaffoldTest.kt
index 31e8240..affbb5e 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomSheetScaffoldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomSheetScaffoldTest.kt
@@ -466,7 +466,7 @@
}
}
rule.runOnIdle {
- Truth.assertThat(innerPadding.bottom).isEqualTo(peekHeight)
+ Truth.assertThat(innerPadding.calculateBottomPadding()).isEqualTo(peekHeight)
}
}
}
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/DrawerScreenshotTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/DrawerScreenshotTest.kt
index f1c3484..47004ca 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/DrawerScreenshotTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/DrawerScreenshotTest.kt
@@ -40,6 +40,7 @@
@LargeTest
@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalMaterialApi::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class DrawerScreenshotTest {
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/DrawerTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/DrawerTest.kt
index 94dca3c..68b88c6 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/DrawerTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/DrawerTest.kt
@@ -57,6 +57,7 @@
@MediumTest
@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalMaterialApi::class)
class DrawerTest {
@get:Rule
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/IconTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/IconTest.kt
index 6a9b98d..4c7ad9a 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/IconTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/IconTest.kt
@@ -27,7 +27,7 @@
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.drawscope.CanvasDrawScope
import androidx.compose.ui.graphics.painter.ColorPainter
-import androidx.compose.ui.graphics.painter.ImagePainter
+import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.testTag
@@ -143,8 +143,8 @@
ImageBitmap(width.roundToPx(), height.roundToPx())
}
- val imagePainter = ImagePainter(image)
- Icon(imagePainter, null)
+ val bitmapPainter = BitmapPainter(image)
+ Icon(bitmapPainter, null)
}
.assertWidthIsEqualTo(width)
.assertHeightIsEqualTo(height)
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ListItemTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ListItemTest.kt
index de7c9ef..c16b858 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ListItemTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ListItemTest.kt
@@ -44,6 +44,7 @@
@MediumTest
@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalMaterialApi::class)
class ListItemTest {
@get:Rule
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MaterialRippleThemeTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MaterialRippleThemeTest.kt
index a4e1833..9bb861c 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MaterialRippleThemeTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MaterialRippleThemeTest.kt
@@ -53,6 +53,7 @@
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress
import androidx.test.screenshot.AndroidXScreenshotTestRule
@@ -456,6 +457,7 @@
)
}
+ @FlakyTest(bugId = 179292401)
@Test
fun customRippleTheme_dragged() {
val interactionState = InteractionState()
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MaterialTextSelectionColorsScreenshotTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MaterialTextSelectionColorsScreenshotTest.kt
index 34a8431..d545fa5 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MaterialTextSelectionColorsScreenshotTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MaterialTextSelectionColorsScreenshotTest.kt
@@ -37,6 +37,7 @@
import androidx.compose.ui.test.width
import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress
import androidx.test.screenshot.AndroidXScreenshotTestRule
@@ -122,6 +123,7 @@
.assertAgainstGolden(screenshotRule, "text_darkThemeSelectionColors")
}
+ @FlakyTest(bugId = 179292401)
@Test
fun filledTextField_lightThemeSelectionColors() {
rule.setContent {
@@ -150,6 +152,7 @@
.assertAgainstGolden(screenshotRule, "filledTextField_lightThemeSelectionColors")
}
+ @FlakyTest(bugId = 179292401)
@Test
fun filledTextField_darkThemeSelectionColors() {
rule.setContent {
@@ -178,6 +181,7 @@
.assertAgainstGolden(screenshotRule, "filledTextField_darkThemeSelectionColors")
}
+ @FlakyTest(bugId = 179292401)
@Test
fun outlinedTextField_lightThemeSelectionColors() {
rule.setContent {
@@ -206,6 +210,7 @@
.assertAgainstGolden(screenshotRule, "outlinedTextField_lightThemeSelectionColors")
}
+ @FlakyTest(bugId = 179292401)
@Test
fun outlinedTextField_darkThemeSelectionColors() {
rule.setContent {
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldTest.kt
index cf5f2d4..35ef679 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldTest.kt
@@ -448,7 +448,8 @@
}
rule.runOnIdle {
with(rule.density) {
- assertThat(innerPadding.bottom).isEqualTo(bottomBarSize.toSize().height.toDp())
+ assertThat(innerPadding.calculateBottomPadding())
+ .isEqualTo(bottomBarSize.toSize().height.toDp())
}
}
}
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldScreenshotTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldScreenshotTest.kt
index 6abdcc4..82ec65c 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldScreenshotTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldScreenshotTest.kt
@@ -106,6 +106,7 @@
assertAgainstGolden("outlined_textField_not_focused")
}
+ @FlakyTest(bugId = 179292401)
@Test
fun outlinedTextField_focused() {
rule.setMaterialContent {
@@ -124,6 +125,7 @@
assertAgainstGolden("outlined_textField_focused")
}
+ @FlakyTest(bugId = 179292401)
@Test
fun outlinedTextField_focused_rtl() {
rule.setMaterialContent {
@@ -144,6 +146,7 @@
assertAgainstGolden("outlined_textField_focused_rtl")
}
+ @FlakyTest(bugId = 179292401)
@Test
fun outlinedTextField_error_focused() {
rule.setMaterialContent {
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt
index 9eb6f1da..7ae3a17 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt
@@ -58,7 +58,6 @@
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performGesture
-import androidx.compose.ui.test.performImeAction
import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.SoftwareKeyboardController
import androidx.compose.ui.text.input.ImeAction
@@ -743,30 +742,4 @@
assertThat(controller).isNotNull()
}
}
-
- @Test
- fun testOutlinedTextField_imeActionCallback_withSoftwareKeyboardController() {
- var controller: SoftwareKeyboardController? = null
-
- rule.setMaterialContent {
- OutlinedTextField(
- modifier = Modifier.testTag(TextfieldTag),
- value = "",
- onValueChange = {},
- label = {},
- keyboardOptions = KeyboardOptions(imeAction = ImeAction.Go),
- onImeActionPerformed = { _, softwareKeyboardController ->
- controller = softwareKeyboardController
- }
- )
- }
- assertThat(controller).isNull()
-
- rule.onNodeWithTag(TextfieldTag)
- .performImeAction()
-
- rule.runOnIdle {
- assertThat(controller).isNotNull()
- }
- }
}
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
index b11a528..532b5b7 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
@@ -68,7 +68,6 @@
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performGesture
-import androidx.compose.ui.test.performImeAction
import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.SoftwareKeyboardController
import androidx.compose.ui.text.input.ImeAction
@@ -948,32 +947,6 @@
}
}
- @Test
- fun testTextField_imeActionCallback_withSoftwareKeyboardController() {
- var controller: SoftwareKeyboardController? = null
-
- rule.setMaterialContent {
- TextField(
- modifier = Modifier.testTag(TextfieldTag),
- value = "",
- onValueChange = {},
- label = {},
- keyboardOptions = KeyboardOptions(imeAction = ImeAction.Go),
- onImeActionPerformed = { _, softwareKeyboardController ->
- controller = softwareKeyboardController
- }
- )
- }
- assertThat(controller).isNull()
-
- rule.onNodeWithTag(TextfieldTag)
- .performImeAction()
-
- rule.runOnIdle {
- assertThat(controller).isNotNull()
- }
- }
-
private val View.isSoftwareKeyboardShown: Boolean
get() {
val inputMethodManager =
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Button.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Button.kt
index a3396d0..d25ae3d 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Button.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Button.kt
@@ -469,9 +469,11 @@
/**
* The default content padding used by [TextButton]
*/
- val TextButtonContentPadding = ContentPadding.copy(
+ val TextButtonContentPadding = PaddingValues(
start = TextButtonHorizontalPadding,
- end = TextButtonHorizontalPadding
+ top = ContentPadding.calculateTopPadding(),
+ end = TextButtonHorizontalPadding,
+ bottom = ContentPadding.calculateBottomPadding()
)
}
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Drawer.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Drawer.kt
index c30b65e..cccb0fb 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Drawer.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Drawer.kt
@@ -453,7 +453,7 @@
* @throws IllegalStateException when parent has [Float.POSITIVE_INFINITY] height
*/
@Composable
-@OptIn(ExperimentalMaterialApi::class)
+@ExperimentalMaterialApi
fun BottomDrawerLayout(
drawerContent: @Composable ColumnScope.() -> Unit,
modifier: Modifier = Modifier,
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Icon.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Icon.kt
index c00e0fd..92af4da 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Icon.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Icon.kt
@@ -26,7 +26,7 @@
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.ImageBitmap
-import androidx.compose.ui.graphics.painter.ImagePainter
+import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.toolingGraphicsLayer
import androidx.compose.ui.graphics.vector.ImageVector
@@ -86,7 +86,7 @@
modifier: Modifier = Modifier,
tint: Color = LocalContentColor.current
) {
- val painter = remember(bitmap) { ImagePainter(bitmap) }
+ val painter = remember(bitmap) { BitmapPainter(bitmap) }
Icon(
painter = painter,
contentDescription = contentDescription,
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ListItem.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ListItem.kt
index eebfa54..cd5631b 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ListItem.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ListItem.kt
@@ -65,6 +65,7 @@
* @param text The primary text of the list item
*/
@Composable
+@ExperimentalMaterialApi
fun ListItem(
modifier: Modifier = Modifier,
icon: @Composable (() -> Unit)? = null,
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt
index 0f8d993..f1bce85 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt
@@ -22,6 +22,7 @@
import androidx.compose.foundation.layout.defaultMinSizeConstraints
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
@@ -92,6 +93,9 @@
* text field. By default no visual transformation is applied
* @param keyboardOptions software keyboard options that contains configuration such as
* [KeyboardType] and [ImeAction].
+ * @param keyboardActions when the input service emits an IME action, the corresponding callback
+ * is called. Note that this IME action may be different from what you specified in
+ * [KeyboardOptions.imeAction].
* @param singleLine when set to true, this text field becomes a single horizontally scrolling
* text field instead of wrapping onto multiple lines. The keyboard will be informed to not show
* the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the
@@ -99,8 +103,6 @@
* @param maxLines the maximum height in terms of maximum number of visible lines. Should be
* equal or greater than 1. Note that this parameter will be ignored and instead maxLines will be
* set to 1 if [singleLine] is set to true.
- * @param onImeActionPerformed is triggered when the input service performs an [ImeAction].
- * Note that the emitted IME action may be different from what you specified through the
* [KeyboardOptions.imeAction] field. The callback also exposes a [SoftwareKeyboardController]
* instance as a parameter that can be used to request to hide the software keyboard
* @param onTextInputStarted a callback to be invoked when the connection with the platform's text
@@ -133,9 +135,9 @@
isErrorValue: Boolean = false,
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
+ keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = false,
maxLines: Int = Int.MAX_VALUE,
- onImeActionPerformed: (ImeAction, SoftwareKeyboardController?) -> Unit = { _, _ -> },
onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
interactionState: InteractionState = remember { InteractionState() },
activeColor: Color = MaterialTheme.colors.primary,
@@ -166,8 +168,8 @@
isErrorValue = isErrorValue,
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
+ keyboardActions = keyboardActions,
maxLines = maxLines,
- onImeActionPerformed = onImeActionPerformed,
onTextInputStarted = onTextInputStarted,
interactionState = interactionState,
activeColor = activeColor,
@@ -178,6 +180,135 @@
)
}
+// TODO(b/178633932): Remove after Alpha 12.
+/**
+ * Material Design implementation of an
+ * [Outlined TextField](https://material.io/components/text-fields/#outlined-text-field)
+ *
+ * See example usage:
+ * @sample androidx.compose.material.samples.SimpleOutlinedTextFieldSample
+ *
+ * If apart from input text change you also want to observe the cursor location, selection range,
+ * or IME composition use the OutlinedTextField overload with the [TextFieldValue] parameter
+ * instead.
+ *
+ * @param value the input text to be shown in the text field
+ * @param onValueChange the callback that is triggered when the input service updates the text. An
+ * updated text comes as a parameter of the callback
+ * @param modifier a [Modifier] for this text field
+ * @param enabled controls the enabled state of the [OutlinedTextField]. When `false`, the text field will
+ * be neither editable nor focusable, the input of the text field will not be selectable,
+ * visually text field will appear in the disabled UI state
+ * @param readOnly controls the editable state of the [OutlinedTextField]. When `true`, the text
+ * field can not be modified, however, a user can focus it and copy text from it. Read-only text
+ * fields are usually used to display pre-filled forms that user can not edit
+ * @param textStyle the style to be applied to the input text. The default [textStyle] uses the
+ * [AmbientTextStyle] defined by the theme
+ * @param label the optional label to be displayed inside the text field container. The default
+ * text style for internal [Text] is [Typography.caption] when the text field is in focus and
+ * [Typography.subtitle1] when the text field is not in focus
+ * @param placeholder the optional placeholder to be displayed when the text field is in focus and
+ * the input text is empty. The default text style for internal [Text] is [Typography.subtitle1]
+ * @param leadingIcon the optional leading icon to be displayed at the beginning of the text field
+ * container
+ * @param trailingIcon the optional trailing icon to be displayed at the end of the text field
+ * container
+ * @param isErrorValue indicates if the text field's current value is in error. If set to true, the
+ * label, bottom indicator and trailing icon will be displayed in [errorColor] color
+ * @param visualTransformation transforms the visual representation of the input [value].
+ * For example, you can use [androidx.compose.ui.text.input.PasswordVisualTransformation] to create a password
+ * text field. By default no visual transformation is applied
+ * @param keyboardOptions software keyboard options that contains configuration such as
+ * [KeyboardType] and [ImeAction].
+ * @param singleLine when set to true, this text field becomes a single horizontally scrolling
+ * text field instead of wrapping onto multiple lines. The keyboard will be informed to not show
+ * the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the
+ * maxLines attribute will be automatically set to 1.
+ * @param maxLines the maximum height in terms of maximum number of visible lines. Should be
+ * equal or greater than 1. Note that this parameter will be ignored and instead maxLines will be
+ * set to 1 if [singleLine] is set to true.
+ * @param onImeActionPerformed is triggered when the input service performs an [ImeAction].
+ * Note that the emitted IME action may be different from what you specified through the
+ * [KeyboardOptions.imeAction] field. The callback also exposes a [SoftwareKeyboardController]
+ * instance as a parameter that can be used to request to hide the software keyboard
+ * @param onTextInputStarted a callback to be invoked when the connection with the platform's text
+ * input service (e.g. software keyboard on Android) has been established. Called with the
+ * [SoftwareKeyboardController] instance that can be used to request to show or hide the software
+ * keyboard
+ * @param interactionState the [InteractionState] representing the different [Interaction]s
+ * present on this OutlinedTextField. You can create and pass in your own remembered
+ * [InteractionState] if you want to read the [InteractionState] and customize the appearance /
+ * behavior of this OutlinedTextField in different [Interaction]s.
+ * @param activeColor the color of the label, bottom indicator and the cursor when the text field is
+ * in focus
+ * @param inactiveColor the color of either the input text or placeholder when the text field is in
+ * focus, and the color of the label and bottom indicator when the text field is not in focus
+ * @param errorColor the alternative color of the label, bottom indicator, cursor and trailing icon
+ * used when [isErrorValue] is set to true
+ */
+@Suppress("UNUSED_PARAMETER")
+@Deprecated(
+ message = "Instead of onImeActionPerformed, use the keyboardActions parameter to specify " +
+ "IMEAction callbacks.",
+ replaceWith = ReplaceWith(
+ expression = """OutlinedTextField(
+ value,
+ onValueChange,
+ modifier,
+ enabled,
+ readOnly,
+ textStyle,
+ label,
+ placeholder,
+ leadingIcon,
+ trailingIcon,
+ isErrorValue,
+ visualTransformation,
+ keyboardOptions,
+ KeyboardActions(
+ onDone= { },
+ onGo = { },
+ onNext= { },
+ onPrevious= { },
+ onSearch = { },
+ onSend = { }
+ ),
+ singleLine,
+ maxLines,
+ onTextInputStarted,
+ interactionState,
+ activeColor,
+ inactiveColor,
+ errorColor)""",
+ imports = ["androidx.compose.foundation.text.KeyboardActions"]
+ ),
+ level = DeprecationLevel.ERROR
+)
+@Composable
+fun OutlinedTextField(
+ value: String,
+ onValueChange: (String) -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ readOnly: Boolean = false,
+ textStyle: TextStyle = LocalTextStyle.current,
+ label: @Composable (() -> Unit)? = null,
+ placeholder: @Composable (() -> Unit)? = null,
+ leadingIcon: @Composable (() -> Unit)? = null,
+ trailingIcon: @Composable (() -> Unit)? = null,
+ isErrorValue: Boolean = false,
+ visualTransformation: VisualTransformation = VisualTransformation.None,
+ keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
+ singleLine: Boolean = false,
+ maxLines: Int = Int.MAX_VALUE,
+ onImeActionPerformed: (ImeAction, SoftwareKeyboardController?) -> Unit,
+ onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
+ interactionState: InteractionState = remember { InteractionState() },
+ activeColor: Color = MaterialTheme.colors.primary,
+ inactiveColor: Color = MaterialTheme.colors.onSurface,
+ errorColor: Color = MaterialTheme.colors.error
+) = Unit
+
/**
* Material Design implementation of an
* [Outlined TextField](https://material.io/components/text-fields/#outlined-text-field)
@@ -217,6 +348,125 @@
* text field. By default no visual transformation is applied
* @param keyboardOptions software keyboard options that contains configuration such as
* [KeyboardType] and [ImeAction].
+ * @param keyboardActions when the input service emits an IME action, the corresponding callback
+ * is called. Note that this IME action may be different from what you specified in
+ * [KeyboardOptions.imeAction].
+ * @param singleLine when set to true, this text field becomes a single horizontally scrolling
+ * text field instead of wrapping onto multiple lines. The keyboard will be informed to not show
+ * the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the
+ * maxLines attribute will be automatically set to 1.
+ * @param maxLines the maximum height in terms of maximum number of visible lines. Should be
+ * equal or greater than 1. Note that this parameter will be ignored and instead maxLines will be
+ * set to 1 if [singleLine] is set to true.
+ * [KeyboardOptions.imeAction] field. The callback also exposes a [SoftwareKeyboardController]
+ * instance as a parameter that can be used to request to hide the software keyboard.
+ * @param onTextInputStarted a callback to be invoked when the connection with the platform's text
+ * input service (e.g. software keyboard on Android) has been established. Called with the
+ * [SoftwareKeyboardController] instance that can be used to request to show or hide the software
+ * keyboard
+ * @param interactionState the [InteractionState] representing the different [Interaction]s
+ * present on this OutlinedTextField. You can create and pass in your own remembered
+ * [InteractionState] if you want to read the [InteractionState] and customize the appearance /
+ * behavior of this OutlinedTextField in different [Interaction]s.
+ * @param activeColor the color of the label, bottom indicator and the cursor when the text field is
+ * in focus
+ * @param inactiveColor the color of either the input text or placeholder when the text field is in
+ * focus, and the color of the label and bottom indicator when the text field is not in focus
+ * @param errorColor the alternative color of the label, bottom indicator, cursor and trailing icon
+ * used when [isErrorValue] is set to true
+ */
+@Composable
+fun OutlinedTextField(
+ value: TextFieldValue,
+ onValueChange: (TextFieldValue) -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ readOnly: Boolean = false,
+ textStyle: TextStyle = LocalTextStyle.current,
+ label: @Composable (() -> Unit)? = null,
+ placeholder: @Composable (() -> Unit)? = null,
+ leadingIcon: @Composable (() -> Unit)? = null,
+ trailingIcon: @Composable (() -> Unit)? = null,
+ isErrorValue: Boolean = false,
+ visualTransformation: VisualTransformation = VisualTransformation.None,
+ keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
+ keyboardActions: KeyboardActions = KeyboardActions(),
+ singleLine: Boolean = false,
+ maxLines: Int = Int.MAX_VALUE,
+ onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
+ interactionState: InteractionState = remember { InteractionState() },
+ activeColor: Color = MaterialTheme.colors.primary,
+ inactiveColor: Color = MaterialTheme.colors.onSurface,
+ errorColor: Color = MaterialTheme.colors.error
+) {
+ TextFieldImpl(
+ type = TextFieldType.Outlined,
+ enabled = enabled,
+ readOnly = readOnly,
+ value = value,
+ onValueChange = onValueChange,
+ modifier = modifier,
+ singleLine = singleLine,
+ textStyle = textStyle,
+ label = label,
+ placeholder = placeholder,
+ leading = leadingIcon,
+ trailing = trailingIcon,
+ isErrorValue = isErrorValue,
+ visualTransformation = visualTransformation,
+ keyboardOptions = keyboardOptions,
+ keyboardActions = keyboardActions,
+ maxLines = maxLines,
+ onTextInputStarted = onTextInputStarted,
+ interactionState = interactionState,
+ activeColor = activeColor,
+ inactiveColor = inactiveColor,
+ errorColor = errorColor,
+ backgroundColor = Color.Unspecified,
+ shape = RectangleShape
+ )
+}
+
+// TODO(b/178633932): Remove after Alpha 12.
+/**
+ * Material Design implementation of an
+ * [Outlined TextField](https://material.io/components/text-fields/#outlined-text-field)
+ *
+ * See example usage:
+ * @sample androidx.compose.material.samples.OutlinedTextFieldSample
+ *
+ * This overload provides access to the input text, cursor position and selection range and
+ * IME composition. If you only want to observe an input text change, use the OutlinedTextField
+ * overload with the [String] parameter instead.
+ *
+ * @param value the input [TextFieldValue] to be shown in the text field
+ * @param onValueChange the callback that is triggered when the input service updates values in
+ * [TextFieldValue]. An updated [TextFieldValue] comes as a parameter of the callback
+ * @param modifier a [Modifier] for this text field
+ * @param enabled controls the enabled state of the [OutlinedTextField]. When `false`, the text field will
+ * be neither editable nor focusable, the input of the text field will not be selectable,
+ * visually text field will appear in the disabled UI state
+ * @param readOnly controls the editable state of the [OutlinedTextField]. When `true`, the text
+ * field can not be modified, however, a user can focus it and copy text from it. Read-only text
+ * fields are usually used to display pre-filled forms that user can not edit
+ * @param textStyle the style to be applied to the input text. The default [textStyle] uses the
+ * [AmbientTextStyle] defined by the theme
+ * @param label the optional label to be displayed inside the text field container. The default
+ * text style for internal [Text] is [Typography.caption] when the text field is in focus and
+ * [Typography.subtitle1] when the text field is not in focus
+ * @param placeholder the optional placeholder to be displayed when the text field is in focus and
+ * the input text is empty. The default text style for internal [Text] is [Typography.subtitle1]
+ * @param leadingIcon the optional leading icon to be displayed at the beginning of the text field
+ * container
+ * @param trailingIcon the optional trailing icon to be displayed at the end of the text field
+ * container
+ * @param isErrorValue indicates if the text field's current value is in error state. If set to
+ * true, the label, bottom indicator and trailing icon will be displayed in [errorColor] color
+ * @param visualTransformation transforms the visual representation of the input [value].
+ * For example, you can use [androidx.compose.ui.text.input.PasswordVisualTransformation] to create a password
+ * text field. By default no visual transformation is applied
+ * @param keyboardOptions software keyboard options that contains configuration such as
+ * [KeyboardType] and [ImeAction].
* @param singleLine when set to true, this text field becomes a single horizontally scrolling
* text field instead of wrapping onto multiple lines. The keyboard will be informed to not show
* the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the
@@ -243,6 +493,44 @@
* @param errorColor the alternative color of the label, bottom indicator, cursor and trailing icon
* used when [isErrorValue] is set to true
*/
+@Suppress("UNUSED_PARAMETER")
+@Deprecated(
+ message = "Instead of onImeActionPerformed, use the keyboardActions parameter to specify " +
+ "IMEAction callbacks.",
+ replaceWith = ReplaceWith(
+ expression = """OutlinedTextField(
+ value,
+ onValueChange,
+ modifier,
+ enabled,
+ readOnly,
+ textStyle,
+ label,
+ placeholder,
+ leadingIcon,
+ trailingIcon,
+ isErrorValue,
+ visualTransformation,
+ keyboardOptions,
+ KeyboardActions(
+ onDone= { },
+ onGo = { },
+ onNext= { },
+ onPrevious= { },
+ onSearch = { },
+ onSend = { }
+ ),
+ singleLine,
+ maxLines,
+ onTextInputStarted,
+ interactionState,
+ activeColor,
+ inactiveColor,
+ errorColor)""",
+ imports = ["androidx.compose.foundation.text.KeyboardActions"]
+ ),
+ level = DeprecationLevel.ERROR
+)
@Composable
fun OutlinedTextField(
value: TextFieldValue,
@@ -260,40 +548,13 @@
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
singleLine: Boolean = false,
maxLines: Int = Int.MAX_VALUE,
- onImeActionPerformed: (ImeAction, SoftwareKeyboardController?) -> Unit = { _, _ -> },
+ onImeActionPerformed: (ImeAction, SoftwareKeyboardController?) -> Unit,
onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
interactionState: InteractionState = remember { InteractionState() },
activeColor: Color = MaterialTheme.colors.primary,
inactiveColor: Color = MaterialTheme.colors.onSurface,
errorColor: Color = MaterialTheme.colors.error
-) {
- TextFieldImpl(
- type = TextFieldType.Outlined,
- enabled = enabled,
- readOnly = readOnly,
- value = value,
- onValueChange = onValueChange,
- modifier = modifier,
- singleLine = singleLine,
- textStyle = textStyle,
- label = label,
- placeholder = placeholder,
- leading = leadingIcon,
- trailing = trailingIcon,
- isErrorValue = isErrorValue,
- visualTransformation = visualTransformation,
- keyboardOptions = keyboardOptions,
- maxLines = maxLines,
- onImeActionPerformed = onImeActionPerformed,
- onTextInputStarted = onTextInputStarted,
- interactionState = interactionState,
- activeColor = activeColor,
- inactiveColor = inactiveColor,
- errorColor = errorColor,
- backgroundColor = Color.Unspecified,
- shape = RectangleShape
- )
-}
+) = Unit
@Composable
internal fun OutlinedTextFieldLayout(
@@ -303,10 +564,10 @@
enabled: Boolean,
readOnly: Boolean,
keyboardOptions: KeyboardOptions,
+ keyboardActions: KeyboardActions,
textStyle: TextStyle,
singleLine: Boolean,
maxLines: Int = Int.MAX_VALUE,
- onImeActionPerformed: (ImeAction) -> Unit = {},
visualTransformation: VisualTransformation,
onTextInputStarted: (SoftwareKeyboardController) -> Unit,
interactionState: InteractionState,
@@ -350,8 +611,8 @@
cursorColor = cursorColor,
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
+ keyboardActions = keyboardActions,
interactionState = interactionState,
- onImeActionPerformed = onImeActionPerformed,
onTextInputStarted = onTextInputStarted,
singleLine = singleLine,
maxLines = maxLines,
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Shapes.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Shapes.kt
index 2185a8b..920f892 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Shapes.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Shapes.kt
@@ -46,7 +46,7 @@
*/
val medium: CornerBasedShape = RoundedCornerShape(4.dp),
/**
- * Shape used by large components like [ModalDrawerLayout] or [BottomDrawerLayout].
+ * Shape used by large components like [ModalDrawerLayout] or [ModalBottomSheetLayout].
*/
val large: CornerBasedShape = RoundedCornerShape(0.dp)
) {
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt
index f243f16..5e5f2b6 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt
@@ -24,6 +24,7 @@
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.ZeroCornerSize
import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@@ -119,6 +120,9 @@
* text field. By default no visual transformation is applied
* @param keyboardOptions software keyboard options that contains configuration such as
* [KeyboardType] and [ImeAction].
+ * @param keyboardActions when the input service emits an IME action, the corresponding callback
+ * is called. Note that this IME action may be different from what you specified in
+ * [KeyboardOptions.imeAction].
* @param singleLine when set to true, this text field becomes a single horizontally scrolling
* text field instead of wrapping onto multiple lines. The keyboard will be informed to not show
* the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the
@@ -126,8 +130,6 @@
* @param maxLines the maximum height in terms of maximum number of visible lines. Should be
* equal or greater than 1. Note that this parameter will be ignored and instead maxLines will be
* set to 1 if [singleLine] is set to true.
- * @param onImeActionPerformed is triggered when the input service performs an [ImeAction].
- * Note that the emitted IME action may be different from what you specified through the
* [KeyboardOptions.imeAction] field. The callback also exposes a [SoftwareKeyboardController]
* instance as a parameter that can be used to request to hide the software keyboard
* @param onTextInputStarted a callback to be invoked when the connection with the platform's text
@@ -162,9 +164,9 @@
isErrorValue: Boolean = false,
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
+ keyboardActions: KeyboardActions = KeyboardActions(),
singleLine: Boolean = false,
maxLines: Int = Int.MAX_VALUE,
- onImeActionPerformed: (ImeAction, SoftwareKeyboardController?) -> Unit = { _, _ -> },
onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
interactionState: InteractionState = remember { InteractionState() },
activeColor: Color = MaterialTheme.colors.primary,
@@ -198,8 +200,8 @@
isErrorValue = isErrorValue,
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
+ keyboardActions = keyboardActions,
maxLines = maxLines,
- onImeActionPerformed = onImeActionPerformed,
onTextInputStarted = onTextInputStarted,
interactionState = interactionState,
activeColor = activeColor,
@@ -210,6 +212,168 @@
)
}
+// TODO(b/178633932): Remove after Alpha 12.
+/**
+ * Material Design implementation of a
+ * [Filled TextField](https://material.io/components/text-fields/#filled-text-field)
+ *
+ * If you are looking for an outlined version, see [OutlinedTextField].
+ *
+ * A simple single line text field looks like:
+ *
+ * @sample androidx.compose.material.samples.SimpleTextFieldSample
+ *
+ * You may provide a placeholder:
+ *
+ * @sample androidx.compose.material.samples.TextFieldWithPlaceholder
+ *
+ * You can also provide leading and trailing icons:
+ *
+ * @sample androidx.compose.material.samples.TextFieldWithIcons
+ *
+ * To handle the error input state, use [isErrorValue] parameter:
+ *
+ * @sample androidx.compose.material.samples.TextFieldWithErrorState
+ *
+ * Additionally, you may provide additional message at the bottom:
+ *
+ * @sample androidx.compose.material.samples.TextFieldWithHelperMessage
+ *
+ * Password text field example:
+ *
+ * @sample androidx.compose.material.samples.PasswordTextField
+ *
+ * Hiding a software keyboard on IME action performed:
+ *
+ * @sample androidx.compose.material.samples.TextFieldWithHideKeyboardOnImeAction
+ *
+ * If apart from input text change you also want to observe the cursor location, selection range,
+ * or IME composition use the TextField overload with the [TextFieldValue] parameter instead.
+ *
+ * @param value the input text to be shown in the text field
+ * @param onValueChange the callback that is triggered when the input service updates the text. An
+ * updated text comes as a parameter of the callback
+ * @param modifier a [Modifier] for this text field
+ * @param enabled controls the enabled state of the [TextField]. When `false`, the text field will
+ * be neither editable nor focusable, the input of the text field will not be selectable,
+ * visually text field will appear in the disabled UI state
+ * @param readOnly controls the editable state of the [TextField]. When `true`, the text
+ * field can not be modified, however, a user can focus it and copy text from it. Read-only text
+ * fields are usually used to display pre-filled forms that user can not edit
+ * @param textStyle the style to be applied to the input text. The default [textStyle] uses the
+ * [AmbientTextStyle] defined by the theme
+ * @param label the optional label to be displayed inside the text field container. The default
+ * text style for internal [Text] is [Typography.caption] when the text field is in focus and
+ * [Typography.subtitle1] when the text field is not in focus
+ * @param placeholder the optional placeholder to be displayed when the text field is in focus and
+ * the input text is empty. The default text style for internal [Text] is [Typography.subtitle1]
+ * @param leadingIcon the optional leading icon to be displayed at the beginning of the text field
+ * container
+ * @param trailingIcon the optional trailing icon to be displayed at the end of the text field
+ * container
+ * @param isErrorValue indicates if the text field's current value is in error. If set to true, the
+ * label, bottom indicator and trailing icon will be displayed in [errorColor] color
+ * @param visualTransformation transforms the visual representation of the input [value].
+ * For example, you can use [androidx.compose.ui.text.input.PasswordVisualTransformation] to create a password
+ * text field. By default no visual transformation is applied
+ * @param keyboardOptions software keyboard options that contains configuration such as
+ * [KeyboardType] and [ImeAction].
+ * @param singleLine when set to true, this text field becomes a single horizontally scrolling
+ * text field instead of wrapping onto multiple lines. The keyboard will be informed to not show
+ * the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the
+ * maxLines attribute will be automatically set to 1.
+ * @param maxLines the maximum height in terms of maximum number of visible lines. Should be
+ * equal or greater than 1. Note that this parameter will be ignored and instead maxLines will be
+ * set to 1 if [singleLine] is set to true.
+ * @param onImeActionPerformed is triggered when the input service performs an [ImeAction].
+ * Note that the emitted IME action may be different from what you specified through the
+ * [KeyboardOptions.imeAction] field. The callback also exposes a [SoftwareKeyboardController]
+ * instance as a parameter that can be used to request to hide the software keyboard
+ * @param onTextInputStarted a callback to be invoked when the connection with the platform's text
+ * input service (e.g. software keyboard on Android) has been established. Called with the
+ * [SoftwareKeyboardController] instance that can be used to request to show or hide the software
+ * keyboard
+ * @param interactionState the [InteractionState] representing the different [Interaction]s
+ * present on this TextField. You can create and pass in your own remembered
+ * [InteractionState] if you want to read the [InteractionState] and customize the appearance /
+ * behavior of this TextField in different [Interaction]s.
+ * @param activeColor the color of the label, bottom indicator and the cursor when the text field is
+ * in focus
+ * @param inactiveColor the color of either the input text or placeholder when the text field is in
+ * focus, and the color of the label and bottom indicator when the text field is not in focus
+ * @param errorColor the alternative color of the label, bottom indicator, cursor and trailing icon
+ * used when [isErrorValue] is set to true
+ * @param backgroundColor the background color of the text field's container
+ * @param shape the shape of the text field's container
+ */
+@Suppress("UNUSED_PARAMETER")
+@Deprecated(
+ message = "Instead of onImeActionPerformed, use the keyboardActions parameter to specify " +
+ "IMEAction callbacks.",
+ replaceWith = ReplaceWith(
+ expression = """TextField(
+ value,
+ onValueChange,
+ modifier,
+ enabled,
+ readOnly,
+ textStyle,
+ label,
+ placeholder,
+ leadingIcon,
+ trailingIcon,
+ isErrorValue,
+ visualTransformation,
+ keyboardOptions,
+ KeyboardActions(
+ onDone= { },
+ onGo = { },
+ onNext= { },
+ onPrevious= { },
+ onSearch = { },
+ onSend = { }
+ ),
+ singleLine,
+ maxLines,
+ onTextInputStarted,
+ interactionState,
+ activeColor,
+ inactiveColor,
+ errorColor,
+ backgroundColor,
+ shape)""",
+ imports = ["androidx.compose.foundation.text.KeyboardActions"]
+ ),
+ level = DeprecationLevel.ERROR
+)
+@Composable
+fun TextField(
+ value: String,
+ onValueChange: (String) -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ readOnly: Boolean = false,
+ textStyle: TextStyle = LocalTextStyle.current,
+ label: @Composable (() -> Unit)? = null,
+ placeholder: @Composable (() -> Unit)? = null,
+ leadingIcon: @Composable (() -> Unit)? = null,
+ trailingIcon: @Composable (() -> Unit)? = null,
+ isErrorValue: Boolean = false,
+ visualTransformation: VisualTransformation = VisualTransformation.None,
+ keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
+ singleLine: Boolean = false,
+ maxLines: Int = Int.MAX_VALUE,
+ onImeActionPerformed: (ImeAction, SoftwareKeyboardController?) -> Unit,
+ onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
+ interactionState: InteractionState = remember { InteractionState() },
+ activeColor: Color = MaterialTheme.colors.primary,
+ inactiveColor: Color = MaterialTheme.colors.onSurface,
+ errorColor: Color = MaterialTheme.colors.error,
+ backgroundColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContainerAlpha),
+ shape: Shape =
+ MaterialTheme.shapes.small.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize)
+) = Unit
+
/**
* Material Design implementation of a
* [Filled TextField](https://material.io/components/text-fields/#filled-text-field)
@@ -251,6 +415,132 @@
* text field. By default no visual transformation is applied
* @param keyboardOptions software keyboard options that contains configuration such as
* [KeyboardType] and [ImeAction].
+ * @param keyboardActions when the input service emits an IME action, the corresponding callback
+ * is called. Note that this IME action may be different from what you specified in
+ * [KeyboardOptions.imeAction].
+ * @param singleLine when set to true, this text field becomes a single horizontally scrolling
+ * text field instead of wrapping onto multiple lines. The keyboard will be informed to not show
+ * the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the
+ * maxLines attribute will be automatically set to 1.
+ * @param maxLines the maximum height in terms of maximum number of visible lines. Should be
+ * equal or greater than 1. Note that this parameter will be ignored and instead maxLines will be
+ * set to 1 if [singleLine] is set to true.
+ * [KeyboardOptions.imeAction] field. The callback also exposes a [SoftwareKeyboardController]
+ * instance as a parameter that can be used to request to hide the software keyboard
+ * @param onTextInputStarted a callback to be invoked when the connection with the platform's text
+ * input service (e.g. software keyboard on Android) has been established. Called with the
+ * [SoftwareKeyboardController] instance that can be used to request to show or hide the software
+ * keyboard
+ * @param interactionState the [InteractionState] representing the different [Interaction]s
+ * present on this TextField. You can create and pass in your own remembered
+ * [InteractionState] if you want to read the [InteractionState] and customize the appearance /
+ * behavior of this TextField in different [Interaction]s.
+ * @param activeColor the color of the label, bottom indicator and the cursor when the text field is
+ * in focus
+ * @param inactiveColor the color of either the input text or placeholder when the text field is in
+ * focus, and the color of the label and bottom indicator when the text field is not in focus
+ * @param errorColor the alternative color of the label, bottom indicator, cursor and trailing icon
+ * used when [isErrorValue] is set to true
+ * @param backgroundColor the background color of the text field's container
+ * @param shape the shape of the text field's container
+ */
+@Composable
+fun TextField(
+ value: TextFieldValue,
+ onValueChange: (TextFieldValue) -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ readOnly: Boolean = false,
+ textStyle: TextStyle = LocalTextStyle.current,
+ label: @Composable (() -> Unit)? = null,
+ placeholder: @Composable (() -> Unit)? = null,
+ leadingIcon: @Composable (() -> Unit)? = null,
+ trailingIcon: @Composable (() -> Unit)? = null,
+ isErrorValue: Boolean = false,
+ visualTransformation: VisualTransformation = VisualTransformation.None,
+ keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
+ keyboardActions: KeyboardActions = KeyboardActions(),
+ singleLine: Boolean = false,
+ maxLines: Int = Int.MAX_VALUE,
+ onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
+ interactionState: InteractionState = remember { InteractionState() },
+ activeColor: Color = MaterialTheme.colors.primary,
+ inactiveColor: Color = MaterialTheme.colors.onSurface,
+ errorColor: Color = MaterialTheme.colors.error,
+ backgroundColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContainerAlpha),
+ shape: Shape =
+ MaterialTheme.shapes.small.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize)
+) {
+ TextFieldImpl(
+ type = TextFieldType.Filled,
+ enabled = enabled,
+ readOnly = readOnly,
+ value = value,
+ onValueChange = onValueChange,
+ modifier = modifier,
+ singleLine = singleLine,
+ textStyle = textStyle,
+ label = label,
+ placeholder = placeholder,
+ leading = leadingIcon,
+ trailing = trailingIcon,
+ isErrorValue = isErrorValue,
+ visualTransformation = visualTransformation,
+ keyboardOptions = keyboardOptions,
+ keyboardActions = keyboardActions,
+ maxLines = maxLines,
+ onTextInputStarted = onTextInputStarted,
+ interactionState = interactionState,
+ activeColor = activeColor,
+ inactiveColor = inactiveColor,
+ errorColor = errorColor,
+ backgroundColor = backgroundColor,
+ shape = shape
+ )
+}
+
+// TODO(b/178633932): Remove after Alpha 12.
+/**
+ * Material Design implementation of a
+ * [Filled TextField](https://material.io/components/text-fields/#filled-text-field)
+ *
+ * If you are looking for an outlined version, see [OutlinedTextField].
+ *
+ * See example usage:
+ * @sample androidx.compose.material.samples.TextFieldSample
+ *
+ * This overload provides access to the input text, cursor position, selection range and
+ * IME composition. If you only want to observe an input text change, use the TextField
+ * overload with the [String] parameter instead.
+ *
+ * @param value the input [TextFieldValue] to be shown in the text field
+ * @param onValueChange the callback that is triggered when the input service updates values in
+ * [TextFieldValue]. An updated [TextFieldValue] comes as a parameter of the callback
+ * @param modifier a [Modifier] for this text field
+ * @param enabled controls the enabled state of the [TextField]. When `false`, the text field will
+ * be neither editable nor focusable, the input of the text field will not be selectable,
+ * visually text field will appear in the disabled UI state
+ * @param readOnly controls the editable state of the [TextField]. When `true`, the text
+ * field can not be modified, however, a user can focus it and copy text from it. Read-only text
+ * fields are usually used to display pre-filled forms that user can not edit
+ * @param textStyle the style to be applied to the input text. The default [textStyle] uses the
+ * [AmbientTextStyle] defined by the theme
+ * @param label the optional label to be displayed inside the text field container. The default
+ * text style for internal [Text] is [Typography.caption] when the text field is in focus and
+ * [Typography.subtitle1] when the text field is not in focus
+ * @param placeholder the optional placeholder to be displayed when the text field is in focus and
+ * the input text is empty. The default text style for internal [Text] is [Typography.subtitle1]
+ * @param leadingIcon the optional leading icon to be displayed at the beginning of the text field
+ * container
+ * @param trailingIcon the optional trailing icon to be displayed at the end of the text field
+ * container
+ * @param isErrorValue indicates if the text field's current value is in error state. If set to
+ * true, the label, bottom indicator and trailing icon will be displayed in [errorColor] color
+ * @param visualTransformation transforms the visual representation of the input [value].
+ * For example, you can use [androidx.compose.ui.text.input.PasswordVisualTransformation] to create a password
+ * text field. By default no visual transformation is applied
+ * @param keyboardOptions software keyboard options that contains configuration such as
+ * [KeyboardType] and [ImeAction].
* @param singleLine when set to true, this text field becomes a single horizontally scrolling
* text field instead of wrapping onto multiple lines. The keyboard will be informed to not show
* the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the
@@ -279,6 +569,46 @@
* @param backgroundColor the background color of the text field's container
* @param shape the shape of the text field's container
*/
+@Suppress("UNUSED_PARAMETER")
+@Deprecated(
+ message = "Instead of onImeActionPerformed, use the keyboardActions parameter to specify " +
+ "IMEAction callbacks.",
+ replaceWith = ReplaceWith(
+ expression = """TextField(
+ value,
+ onValueChange,
+ modifier,
+ enabled,
+ readOnly,
+ textStyle,
+ label,
+ placeholder,
+ leadingIcon,
+ trailingIcon,
+ isErrorValue,
+ visualTransformation,
+ keyboardOptions,
+ KeyboardActions(
+ onDone= { },
+ onGo = { },
+ onNext= { },
+ onPrevious= { },
+ onSearch = { },
+ onSend = { }
+ ),
+ singleLine,
+ maxLines,
+ onTextInputStarted,
+ interactionState,
+ activeColor,
+ inactiveColor,
+ errorColor,
+ backgroundColor,
+ shape)""",
+ imports = ["androidx.compose.foundation.text.KeyboardActions"]
+ ),
+ level = DeprecationLevel.ERROR
+)
@Composable
fun TextField(
value: TextFieldValue,
@@ -296,7 +626,7 @@
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
singleLine: Boolean = false,
maxLines: Int = Int.MAX_VALUE,
- onImeActionPerformed: (ImeAction, SoftwareKeyboardController?) -> Unit = { _, _ -> },
+ onImeActionPerformed: (ImeAction, SoftwareKeyboardController?) -> Unit,
onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
interactionState: InteractionState = remember { InteractionState() },
activeColor: Color = MaterialTheme.colors.primary,
@@ -305,34 +635,7 @@
backgroundColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContainerAlpha),
shape: Shape =
MaterialTheme.shapes.small.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize)
-) {
- TextFieldImpl(
- type = TextFieldType.Filled,
- enabled = enabled,
- readOnly = readOnly,
- value = value,
- onValueChange = onValueChange,
- modifier = modifier,
- singleLine = singleLine,
- textStyle = textStyle,
- label = label,
- placeholder = placeholder,
- leading = leadingIcon,
- trailing = trailingIcon,
- isErrorValue = isErrorValue,
- visualTransformation = visualTransformation,
- keyboardOptions = keyboardOptions,
- maxLines = maxLines,
- onImeActionPerformed = onImeActionPerformed,
- onTextInputStarted = onTextInputStarted,
- interactionState = interactionState,
- activeColor = activeColor,
- inactiveColor = inactiveColor,
- errorColor = errorColor,
- backgroundColor = backgroundColor,
- shape = shape
- )
-}
+) = Unit
@Composable
internal fun TextFieldLayout(
@@ -342,10 +645,10 @@
enabled: Boolean,
readOnly: Boolean,
keyboardOptions: KeyboardOptions,
+ keyboardActions: KeyboardActions,
textStyle: TextStyle,
singleLine: Boolean,
maxLines: Int = Int.MAX_VALUE,
- onImeActionPerformed: (ImeAction) -> Unit = {},
visualTransformation: VisualTransformation,
onTextInputStarted: (SoftwareKeyboardController) -> Unit,
interactionState: InteractionState,
@@ -378,8 +681,8 @@
cursorColor = cursorColor,
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
+ keyboardActions = keyboardActions,
interactionState = interactionState,
- onImeActionPerformed = onImeActionPerformed,
onTextInputStarted = onTextInputStarted,
singleLine = singleLine,
maxLines = maxLines,
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextFieldImpl.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextFieldImpl.kt
index bae7721..05e2f63 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextFieldImpl.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextFieldImpl.kt
@@ -27,6 +27,7 @@
import androidx.compose.foundation.Interaction
import androidx.compose.foundation.InteractionState
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Providers
@@ -48,7 +49,6 @@
import androidx.compose.ui.text.InternalTextApi
import androidx.compose.ui.text.SoftwareKeyboardController
import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.lerp
@@ -83,8 +83,8 @@
isErrorValue: Boolean,
visualTransformation: VisualTransformation,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
+ keyboardActions: KeyboardActions,
maxLines: Int = Int.MAX_VALUE,
- onImeActionPerformed: (ImeAction, SoftwareKeyboardController?) -> Unit,
onTextInputStarted: (SoftwareKeyboardController) -> Unit,
interactionState: InteractionState,
activeColor: Color,
@@ -167,9 +167,6 @@
} else null
val cursorColor = if (isErrorValue) errorColor else activeColor
- val onImeActionPerformedAction: (ImeAction) -> Unit = {
- onImeActionPerformed(it, keyboardController.value)
- }
val onTextInputStartedAction: (SoftwareKeyboardController) -> Unit = {
keyboardController.value = it
onTextInputStarted(it)
@@ -183,10 +180,10 @@
enabled = enabled,
readOnly = readOnly,
keyboardOptions = keyboardOptions,
+ keyboardActions = keyboardActions,
textStyle = mergedTextStyle,
singleLine = singleLine,
maxLines = maxLines,
- onImeActionPerformed = onImeActionPerformedAction,
visualTransformation = visualTransformation,
onTextInputStarted = onTextInputStartedAction,
interactionState = interactionState,
@@ -212,10 +209,10 @@
enabled = enabled,
readOnly = readOnly,
keyboardOptions = keyboardOptions,
+ keyboardActions = keyboardActions,
textStyle = mergedTextStyle,
singleLine = singleLine,
maxLines = maxLines,
- onImeActionPerformed = onImeActionPerformedAction,
visualTransformation = visualTransformation,
onTextInputStarted = onTextInputStartedAction,
interactionState = interactionState,
diff --git a/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/AndroidSnapshotTests.kt b/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/AndroidSnapshotTests.kt
index d97f300..6bea0fc 100644
--- a/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/AndroidSnapshotTests.kt
+++ b/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/AndroidSnapshotTests.kt
@@ -18,12 +18,12 @@
import androidx.compose.runtime.snapshots.Snapshot
import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.MediumTest
+import androidx.test.filters.LargeTest
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
-@MediumTest
+@LargeTest
@RunWith(AndroidJUnit4::class)
class AndroidSnapshotTests : BaseComposeTest() {
@get:Rule
diff --git a/compose/ui/ui-graphics/api/current.txt b/compose/ui/ui-graphics/api/current.txt
index 07a7b52..c23e824 100644
--- a/compose/ui/ui-graphics/api/current.txt
+++ b/compose/ui/ui-graphics/api/current.txt
@@ -1084,6 +1084,15 @@
package androidx.compose.ui.graphics.painter {
+ public final class BitmapPainter extends androidx.compose.ui.graphics.painter.Painter {
+ method public long getIntrinsicSize-NH-jbRc();
+ method protected void onDraw(androidx.compose.ui.graphics.drawscope.DrawScope);
+ property public long intrinsicSize;
+ }
+
+ public final class BitmapPainterKt {
+ }
+
public final class ColorPainter extends androidx.compose.ui.graphics.painter.Painter {
method public long getColor-0d7_KjU();
method public long getIntrinsicSize-NH-jbRc();
@@ -1092,12 +1101,6 @@
property public long intrinsicSize;
}
- public final class ImagePainter extends androidx.compose.ui.graphics.painter.Painter {
- method public long getIntrinsicSize-NH-jbRc();
- method protected void onDraw(androidx.compose.ui.graphics.drawscope.DrawScope);
- property public long intrinsicSize;
- }
-
public abstract class Painter {
ctor public Painter();
method protected boolean applyAlpha(float alpha);
diff --git a/compose/ui/ui-graphics/api/public_plus_experimental_current.txt b/compose/ui/ui-graphics/api/public_plus_experimental_current.txt
index 07a7b52..c23e824 100644
--- a/compose/ui/ui-graphics/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui-graphics/api/public_plus_experimental_current.txt
@@ -1084,6 +1084,15 @@
package androidx.compose.ui.graphics.painter {
+ public final class BitmapPainter extends androidx.compose.ui.graphics.painter.Painter {
+ method public long getIntrinsicSize-NH-jbRc();
+ method protected void onDraw(androidx.compose.ui.graphics.drawscope.DrawScope);
+ property public long intrinsicSize;
+ }
+
+ public final class BitmapPainterKt {
+ }
+
public final class ColorPainter extends androidx.compose.ui.graphics.painter.Painter {
method public long getColor-0d7_KjU();
method public long getIntrinsicSize-NH-jbRc();
@@ -1092,12 +1101,6 @@
property public long intrinsicSize;
}
- public final class ImagePainter extends androidx.compose.ui.graphics.painter.Painter {
- method public long getIntrinsicSize-NH-jbRc();
- method protected void onDraw(androidx.compose.ui.graphics.drawscope.DrawScope);
- property public long intrinsicSize;
- }
-
public abstract class Painter {
ctor public Painter();
method protected boolean applyAlpha(float alpha);
diff --git a/compose/ui/ui-graphics/api/restricted_current.txt b/compose/ui/ui-graphics/api/restricted_current.txt
index 59ed29d..add6dc4 100644
--- a/compose/ui/ui-graphics/api/restricted_current.txt
+++ b/compose/ui/ui-graphics/api/restricted_current.txt
@@ -1140,6 +1140,15 @@
package androidx.compose.ui.graphics.painter {
+ public final class BitmapPainter extends androidx.compose.ui.graphics.painter.Painter {
+ method public long getIntrinsicSize-NH-jbRc();
+ method protected void onDraw(androidx.compose.ui.graphics.drawscope.DrawScope);
+ property public long intrinsicSize;
+ }
+
+ public final class BitmapPainterKt {
+ }
+
public final class ColorPainter extends androidx.compose.ui.graphics.painter.Painter {
method public long getColor-0d7_KjU();
method public long getIntrinsicSize-NH-jbRc();
@@ -1148,12 +1157,6 @@
property public long intrinsicSize;
}
- public final class ImagePainter extends androidx.compose.ui.graphics.painter.Painter {
- method public long getIntrinsicSize-NH-jbRc();
- method protected void onDraw(androidx.compose.ui.graphics.drawscope.DrawScope);
- property public long intrinsicSize;
- }
-
public abstract class Painter {
ctor public Painter();
method protected boolean applyAlpha(float alpha);
diff --git a/compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/painter/ImagePainterTest.kt b/compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/painter/BitmapPainterTest.kt
similarity index 90%
rename from compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/painter/ImagePainterTest.kt
rename to compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/painter/BitmapPainterTest.kt
index 885cae4..be9ca78 100644
--- a/compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/painter/ImagePainterTest.kt
+++ b/compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/painter/BitmapPainterTest.kt
@@ -39,7 +39,7 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
-class ImagePainterTest {
+class BitmapPainterTest {
val white = Color.White
private val srcSize = Size(100.0f, 100.0f)
@@ -71,10 +71,10 @@
}
@Test
- fun testImagePainter() {
- val imagePainter = ImagePainter(createTestSrcImage())
+ fun testBitmapPainter() {
+ val bitmapPainter = BitmapPainter(createTestSrcImage())
val dst = createTestDstImage()
- drawPainter(imagePainter, Canvas(dst), srcSize)
+ drawPainter(bitmapPainter, Canvas(dst), srcSize)
val pixelmap = dst.toPixelMap()
assertEquals(white, pixelmap[195, 5])
@@ -84,14 +84,14 @@
}
@Test
- fun testImagePainterAppliedAlpha() {
- val imagePainter = ImagePainter(createTestSrcImage())
+ fun testBitmapPainterAppliedAlpha() {
+ val bitmapPainter = BitmapPainter(createTestSrcImage())
val dst = createTestDstImage()
val flagCanvas = LayerFlagCanvas(Canvas(dst))
- drawPainter(imagePainter, flagCanvas, srcSize, alpha = 0.5f)
+ drawPainter(bitmapPainter, flagCanvas, srcSize, alpha = 0.5f)
- // ImagePainter's optimized application of alpha should be applied here
+ // BitmapPainter's optimized application of alpha should be applied here
// instead of Painter's default implementation that invokes Canvas.saveLayer
assertFalse(flagCanvas.saveLayerCalled)
@@ -110,12 +110,12 @@
}
@Test
- fun testImagePainterTint() {
- val imagePainter = ImagePainter(createTestSrcImage())
+ fun testBitmapPainterTint() {
+ val bitmapPainter = BitmapPainter(createTestSrcImage())
val dst = createTestDstImage()
drawPainter(
- imagePainter,
+ bitmapPainter,
Canvas(dst),
srcSize,
colorFilter = ColorFilter.tint(Color.Cyan, BlendMode.SrcIn)
@@ -134,7 +134,7 @@
val dst = createTestDstImage()
val canvas = Canvas(dst)
- val topLeftPainter = ImagePainter(
+ val topLeftPainter = BitmapPainter(
srcImage,
srcOffset = IntOffset.Zero,
srcSize = IntSize(50, 50)
@@ -151,7 +151,7 @@
assertEquals(Color.Blue, topLeftMap[49, 0])
assertEquals(Color.Red, topLeftMap[49, 49])
- val topRightPainter = ImagePainter(
+ val topRightPainter = BitmapPainter(
srcImage,
srcOffset = IntOffset(50, 0),
srcSize = IntSize(50, 50)
@@ -166,7 +166,7 @@
assertEquals(Color.Blue, topRightMap[49, 0])
assertEquals(Color.Blue, topRightMap[49, 49])
- val bottomLeftPainter = ImagePainter(
+ val bottomLeftPainter = BitmapPainter(
srcImage,
srcOffset = IntOffset(0, 50),
srcSize = IntSize(50, 50)
@@ -180,7 +180,7 @@
assertEquals(Color.Blue, bottomLeftMap[0, 49])
assertEquals(Color.Blue, bottomLeftMap[49, 49])
- val bottomRightPainter = ImagePainter(
+ val bottomRightPainter = BitmapPainter(
srcImage,
srcOffset = IntOffset(50, 50),
srcSize = IntSize(50, 50)
@@ -198,7 +198,7 @@
@Test
fun testInvalidLeftBoundThrows() {
try {
- ImagePainter(
+ BitmapPainter(
createTestSrcImage(),
IntOffset(-1, 1),
IntSize(10, 10)
@@ -212,7 +212,7 @@
@Test
fun testInvalidTopBoundThrows() {
try {
- ImagePainter(
+ BitmapPainter(
createTestSrcImage(),
IntOffset(0, -1),
IntSize(10, 10)
@@ -227,7 +227,7 @@
fun testInvalidRightBoundThrows() {
try {
val image = createTestSrcImage()
- ImagePainter(
+ BitmapPainter(
image,
IntOffset(0, 0),
IntSize(image.width + 1, 10)
@@ -242,7 +242,7 @@
fun testInvalidBottomBoundThrows() {
try {
val image = createTestSrcImage()
- ImagePainter(
+ BitmapPainter(
image,
IntOffset(0, 0),
IntSize(10, image.height + 1)
@@ -256,7 +256,7 @@
@Test
fun testRightLessThanLeftThrows() {
try {
- ImagePainter(
+ BitmapPainter(
createTestSrcImage(),
IntOffset(50, 0),
IntSize(-40, 10)
@@ -270,7 +270,7 @@
@Test
fun testTopLessThanBottomThrows() {
try {
- ImagePainter(
+ BitmapPainter(
createTestSrcImage(),
IntOffset(0, 100),
IntSize(-90, -90)
diff --git a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/painter/ImagePainter.kt b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/painter/BitmapPainter.kt
similarity index 91%
rename from compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/painter/ImagePainter.kt
rename to compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/painter/BitmapPainter.kt
index 333632e..17a867e 100644
--- a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/painter/ImagePainter.kt
+++ b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/painter/BitmapPainter.kt
@@ -25,6 +25,15 @@
import androidx.compose.ui.unit.toSize
import kotlin.math.roundToInt
+@Deprecated(
+ "Use BitmapPainter instead",
+ ReplaceWith(
+ "BitmapPainter",
+ "androidx.compose.ui.graphics.painter.BitmapPainter"
+ )
+)
+typealias ImagePainter = BitmapPainter
+
/**
* [Painter] implementation used to draw an [ImageBitmap] into the provided canvas
* This implementation can handle applying alpha and [ColorFilter] to it's drawn result
@@ -39,7 +48,7 @@
* 2) Source size must be greater than zero
* 3) Source size must be less than or equal to the dimensions of [image]
*/
-class ImagePainter(
+class BitmapPainter(
private val image: ImageBitmap,
private val srcOffset: IntOffset = IntOffset.Zero,
private val srcSize: IntSize = IntSize(image.width, image.height)
@@ -94,7 +103,7 @@
override fun equals(other: Any?): Boolean {
if (this === other) return true
- if (other !is ImagePainter) return false
+ if (other !is BitmapPainter) return false
if (image != other.image) return false
if (srcOffset != other.srcOffset) return false
@@ -111,6 +120,6 @@
}
override fun toString(): String {
- return "ImagePainter(image=$image, srcOffset=$srcOffset, srcSize=$srcSize)"
+ return "BitmapPainter(image=$image, srcOffset=$srcOffset, srcSize=$srcSize)"
}
}
\ No newline at end of file
diff --git a/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/TextActionsTest.kt b/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/TextActionsTest.kt
index 44698c4..369a411 100644
--- a/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/TextActionsTest.kt
+++ b/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/TextActionsTest.kt
@@ -18,6 +18,8 @@
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.foundation.text.KeyboardActionScope
+import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
@@ -49,7 +51,7 @@
@OptIn(ExperimentalFoundationApi::class)
fun TextFieldUi(
imeAction: ImeAction = ImeAction.Default,
- onImeActionPerformed: (ImeAction) -> Unit = {},
+ keyboardActions: KeyboardActions = KeyboardActions.Default,
textCallback: (String) -> Unit = {}
) {
val state = remember { mutableStateOf("") }
@@ -57,7 +59,7 @@
modifier = Modifier.testTag(fieldTag),
value = state.value,
keyboardOptions = KeyboardOptions(imeAction = imeAction),
- onImeActionPerformed = onImeActionPerformed,
+ keyboardActions = keyboardActions,
onValueChange = {
state.value = it
textCallback(it)
@@ -170,33 +172,43 @@
@Test
fun sendImeAction_search() {
- var actionPerformed: ImeAction = ImeAction.Default
+ var actionPerformed = false
rule.setContent {
TextFieldUi(
imeAction = ImeAction.Search,
- onImeActionPerformed = { actionPerformed = it }
+ keyboardActions = KeyboardActions(onSearch = { actionPerformed = true })
)
}
- assertThat(actionPerformed).isEqualTo(ImeAction.Default)
+ assertThat(actionPerformed).isFalse()
rule.onNodeWithTag(fieldTag)
.performImeAction()
rule.runOnIdle {
- assertThat(actionPerformed).isEqualTo(ImeAction.Search)
+ assertThat(actionPerformed).isTrue()
}
}
@Test
fun sendImeAction_actionNotDefined_shouldFail() {
- var actionPerformed: ImeAction = ImeAction.Default
+ var actionPerformed = false
+ val anyAction: KeyboardActionScope.() -> Unit = { actionPerformed = true }
rule.setContent {
TextFieldUi(
imeAction = ImeAction.Default,
- onImeActionPerformed = { actionPerformed = it }
+ // TODO(b/179226323): Add API to set the same KeyboardAction lambda for all
+ // ImeActions.
+ keyboardActions = KeyboardActions(
+ onDone = anyAction,
+ onGo = anyAction,
+ onNext = anyAction,
+ onPrevious = anyAction,
+ onSearch = anyAction,
+ onSend = anyAction,
+ )
)
}
- assertThat(actionPerformed).isEqualTo(ImeAction.Default)
+ assertThat(actionPerformed).isFalse()
expectErrorMessageStartsWith(
"" +
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/ImeAction.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/ImeAction.kt
index fcfe71c..d9b6040 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/ImeAction.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/ImeAction.kt
@@ -18,8 +18,7 @@
/**
* Signals the keyboard what type of action should be displayed. It is not guaranteed if
- * the keyboard will show the requested action. Apart from the visuals on the keyboard, when the
- * user performs the action onImeActionPerformed callback will be triggered with the action.
+ * the keyboard will show the requested action.
*/
enum class ImeAction {
/**
@@ -32,7 +31,7 @@
/**
* Represents that no action is expected from the keyboard. Keyboard might choose to show an
* action which mostly will be newline, however this action is not carried into the app via
- * onImeActionPerformed.
+ * any [Keyboard Action][androidx.compose.foundation.text.KeyboardAction].
*/
None,
diff --git a/compose/ui/ui/api/current.txt b/compose/ui/ui/api/current.txt
index c36481e..5305fe5 100644
--- a/compose/ui/ui/api/current.txt
+++ b/compose/ui/ui/api/current.txt
@@ -367,6 +367,7 @@
public final class FocusOrderModifierKt {
method public static androidx.compose.ui.Modifier focusOrder(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.focus.FocusOrder,kotlin.Unit> focusOrderReceiver);
+ method public static androidx.compose.ui.Modifier focusOrder(androidx.compose.ui.Modifier, androidx.compose.ui.focus.FocusRequester focusRequester);
method public static androidx.compose.ui.Modifier focusOrder(androidx.compose.ui.Modifier, androidx.compose.ui.focus.FocusRequester focusRequester, kotlin.jvm.functions.Function1<? super androidx.compose.ui.focus.FocusOrder,kotlin.Unit> focusOrderReceiver);
}
@@ -2083,7 +2084,7 @@
method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.lifecycle.LifecycleOwner> getLocalLifecycleOwner();
method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.savedstate.SavedStateRegistryOwner> getLocalSavedStateRegistryOwner();
method public static androidx.compose.runtime.ProvidableCompositionLocal<android.view.View> getLocalView();
- method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.lifecycle.ViewModelStoreOwner> getLocalViewModelStoreOwner();
+ method @Deprecated public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.lifecycle.ViewModelStoreOwner> getLocalViewModelStoreOwner();
}
public final class AndroidClipboardManagerKt {
@@ -2724,7 +2725,7 @@
}
public final class ViewModelKt {
- method @androidx.compose.runtime.Composable public static <T extends androidx.lifecycle.ViewModel> T viewModel(Class<T> modelClass, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ method @Deprecated @androidx.compose.runtime.Composable public static <T extends androidx.lifecycle.ViewModel> T viewModel(Class<T> modelClass, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
method @androidx.compose.runtime.Composable public static inline <reified T extends androidx.lifecycle.ViewModel> T! viewModel(optional String key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
}
diff --git a/compose/ui/ui/api/public_plus_experimental_current.txt b/compose/ui/ui/api/public_plus_experimental_current.txt
index c36481e..5305fe5 100644
--- a/compose/ui/ui/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui/api/public_plus_experimental_current.txt
@@ -367,6 +367,7 @@
public final class FocusOrderModifierKt {
method public static androidx.compose.ui.Modifier focusOrder(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.focus.FocusOrder,kotlin.Unit> focusOrderReceiver);
+ method public static androidx.compose.ui.Modifier focusOrder(androidx.compose.ui.Modifier, androidx.compose.ui.focus.FocusRequester focusRequester);
method public static androidx.compose.ui.Modifier focusOrder(androidx.compose.ui.Modifier, androidx.compose.ui.focus.FocusRequester focusRequester, kotlin.jvm.functions.Function1<? super androidx.compose.ui.focus.FocusOrder,kotlin.Unit> focusOrderReceiver);
}
@@ -2083,7 +2084,7 @@
method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.lifecycle.LifecycleOwner> getLocalLifecycleOwner();
method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.savedstate.SavedStateRegistryOwner> getLocalSavedStateRegistryOwner();
method public static androidx.compose.runtime.ProvidableCompositionLocal<android.view.View> getLocalView();
- method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.lifecycle.ViewModelStoreOwner> getLocalViewModelStoreOwner();
+ method @Deprecated public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.lifecycle.ViewModelStoreOwner> getLocalViewModelStoreOwner();
}
public final class AndroidClipboardManagerKt {
@@ -2724,7 +2725,7 @@
}
public final class ViewModelKt {
- method @androidx.compose.runtime.Composable public static <T extends androidx.lifecycle.ViewModel> T viewModel(Class<T> modelClass, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ method @Deprecated @androidx.compose.runtime.Composable public static <T extends androidx.lifecycle.ViewModel> T viewModel(Class<T> modelClass, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
method @androidx.compose.runtime.Composable public static inline <reified T extends androidx.lifecycle.ViewModel> T! viewModel(optional String key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
}
diff --git a/compose/ui/ui/api/restricted_current.txt b/compose/ui/ui/api/restricted_current.txt
index 0152d28..eafb45d 100644
--- a/compose/ui/ui/api/restricted_current.txt
+++ b/compose/ui/ui/api/restricted_current.txt
@@ -367,6 +367,7 @@
public final class FocusOrderModifierKt {
method public static androidx.compose.ui.Modifier focusOrder(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.focus.FocusOrder,kotlin.Unit> focusOrderReceiver);
+ method public static androidx.compose.ui.Modifier focusOrder(androidx.compose.ui.Modifier, androidx.compose.ui.focus.FocusRequester focusRequester);
method public static androidx.compose.ui.Modifier focusOrder(androidx.compose.ui.Modifier, androidx.compose.ui.focus.FocusRequester focusRequester, kotlin.jvm.functions.Function1<? super androidx.compose.ui.focus.FocusOrder,kotlin.Unit> focusOrderReceiver);
}
@@ -2160,7 +2161,7 @@
method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.lifecycle.LifecycleOwner> getLocalLifecycleOwner();
method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.savedstate.SavedStateRegistryOwner> getLocalSavedStateRegistryOwner();
method public static androidx.compose.runtime.ProvidableCompositionLocal<android.view.View> getLocalView();
- method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.lifecycle.ViewModelStoreOwner> getLocalViewModelStoreOwner();
+ method @Deprecated public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.lifecycle.ViewModelStoreOwner> getLocalViewModelStoreOwner();
}
public final class AndroidClipboardManagerKt {
@@ -2803,7 +2804,7 @@
}
public final class ViewModelKt {
- method @androidx.compose.runtime.Composable public static <T extends androidx.lifecycle.ViewModel> T viewModel(Class<T> modelClass, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ method @Deprecated @androidx.compose.runtime.Composable public static <T extends androidx.lifecycle.ViewModel> T viewModel(Class<T> modelClass, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
method @androidx.compose.runtime.Composable public static inline <reified T extends androidx.lifecycle.ViewModel> T! viewModel(optional String key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
}
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/UiDemos.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/UiDemos.kt
index 460dcdf..28c6c4a 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/UiDemos.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/UiDemos.kt
@@ -124,7 +124,6 @@
ComposableDemo("Popup") { PopupDemo() },
GraphicsDemos,
GestureDemos,
- ComposableDemo("Views interoperability") { ViewInteropDemo() },
- ComposableDemo("ViewModel") { ViewModelDemo() }
+ ComposableDemo("Views interoperability") { ViewInteropDemo() }
)
)
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/ViewModelDemo.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/ViewModelDemo.kt
deleted file mode 100644
index 4414ae5..0000000
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/ViewModelDemo.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.demos
-
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Column
-import androidx.compose.material.Button
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.livedata.observeAsState
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.viewinterop.viewModel
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.SavedStateHandle
-import androidx.lifecycle.ViewModel
-
-@Composable
-fun ViewModelDemo() {
- Column(
- horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.SpaceEvenly
- ) {
- val countViewModel = viewModel<CountViewModel>()
- val count by countViewModel.count.observeAsState()
- Text("Count is $count")
- Button(onClick = { countViewModel.increaseCount() }) {
- Text("Increase")
- }
- }
-}
-
-class CountViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {
-
- private val CountKey = "${javaClass.simpleName}-count"
-
- val count: LiveData<Int> =
- savedStateHandle.getLiveData(CountKey, 0)
-
- fun increaseCount() {
- savedStateHandle[CountKey] = (count.value ?: 0) + 1
- }
-}
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/PainterModifierTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/PainterModifierTest.kt
index b33c285..e0d42ae 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/PainterModifierTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/PainterModifierTest.kt
@@ -48,7 +48,7 @@
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.graphics.drawscope.DrawScope
-import androidx.compose.ui.graphics.painter.ImagePainter
+import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.graphics.vector.Path
@@ -520,11 +520,11 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@Test
- fun testImagePainterScalesContent() {
- // ImagePainter should handle scaling its content image up to fill the
+ fun testBitmapPainterScalesContent() {
+ // BitmapPainter should handle scaling its content image up to fill the
// corresponding content bounds. Because the composable is twice the
// height of the image and we are providing ContentScale.FillHeight
- // the ImagePainter should draw the image with twice its original
+ // the BitmapPainter should draw the image with twice its original
// height and width centered within the bounds of the composable
val boxWidth = 600
val boxHeight = 400
@@ -542,7 +542,7 @@
.background(color = Color.Gray)
.width((boxWidth / LocalDensity.current.density).dp)
.height((boxHeight / LocalDensity.current.density).dp)
- .paint(ImagePainter(srcImage), contentScale = ContentScale.FillHeight)
+ .paint(BitmapPainter(srcImage), contentScale = ContentScale.FillHeight)
)
}
@@ -567,7 +567,7 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@Test
- fun testImagePainterScalesNonUniformly() {
+ fun testBitmapPainterScalesNonUniformly() {
// The composable dimensions are larger than the ImageBitmap. By not passing in
// a ContentScale parameter to the painter, the ImageBitmap should be stretched
// non-uniformly to fully occupy the bounds of the composable
@@ -587,7 +587,7 @@
.background(color = Color.Gray)
.width((boxWidth / LocalDensity.current.density).dp)
.height((boxHeight / LocalDensity.current.density).dp)
- .paint(ImagePainter(srcImage), contentScale = ContentScale.FillBounds)
+ .paint(BitmapPainter(srcImage), contentScale = ContentScale.FillBounds)
)
}
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CustomFocusTraversalTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CustomFocusTraversalTest.kt
index 57e720e..6295606 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CustomFocusTraversalTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CustomFocusTraversalTest.kt
@@ -79,7 +79,7 @@
)
Box(
Modifier
- .focusRequester(item3)
+ .focusOrder(item3)
.onFocusChanged { item3Focused = it.isFocused }
.focusModifier()
)
@@ -115,7 +115,7 @@
Row {
Box(
Modifier
- .focusRequester(item1)
+ .focusOrder(item1)
.onFocusChanged { item1Focused = it.isFocused }
.focusModifier()
)
@@ -163,7 +163,7 @@
Column {
Box(
Modifier
- .focusRequester(item1)
+ .focusOrder(item1)
.onFocusChanged { item1Focused = it.isFocused }
.focusModifier()
)
@@ -222,7 +222,7 @@
)
Box(
Modifier
- .focusRequester(item3)
+ .focusOrder(item3)
.onFocusChanged { item3Focused = it.isFocused }
.focusModifier()
)
@@ -259,7 +259,7 @@
Row {
Box(
Modifier
- .focusRequester(item1)
+ .focusOrder(item1)
.onFocusChanged { item1Focused = it.isFocused }
.focusModifier()
)
@@ -318,7 +318,7 @@
)
Box(
Modifier
- .focusRequester(item3)
+ .focusOrder(item3)
.onFocusChanged { item3Focused = it.isFocused }
.focusModifier()
)
@@ -357,7 +357,7 @@
Row {
Box(
Modifier
- .focusRequester(item1)
+ .focusOrder(item1)
.onFocusChanged { item1Focused = it.isFocused }
.focusModifier()
)
@@ -418,7 +418,7 @@
)
Box(
Modifier
- .focusRequester(item3)
+ .focusOrder(item3)
.onFocusChanged { item3Focused = it.isFocused }
.focusModifier()
)
@@ -469,13 +469,13 @@
)
Box(
Modifier
- .focusRequester(item3)
+ .focusOrder(item3)
.onFocusChanged { item3Focused = it.isFocused }
.focusModifier()
)
Box(
Modifier
- .focusRequester(item4)
+ .focusOrder(item4)
.onFocusChanged { item4Focused = it.isFocused }
.focusModifier()
)
@@ -525,7 +525,7 @@
)
Box(
Modifier
- .focusRequester(item3)
+ .focusOrder(item3)
.onFocusChanged { item3Focused = it.isFocused }
.focusModifier()
)
@@ -576,7 +576,7 @@
)
Box(
Modifier
- .focusRequester(item3)
+ .focusOrder(item3)
.onFocusChanged { item3Focused = it.isFocused }
.focusModifier()
)
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidAmbients.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidAmbients.kt
index 6f0bbfc..a6323477 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidAmbients.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidAmbients.kt
@@ -132,6 +132,7 @@
/**
* The CompositionLocal containing the current [ViewModelStoreOwner].
*/
+@Suppress("DEPRECATION")
@Deprecated(
"Renamed to LocalViewModelStoreOwner",
replaceWith = ReplaceWith(
@@ -144,6 +145,12 @@
/**
* The CompositionLocal containing the current [ViewModelStoreOwner].
*/
+@Suppress("DeprecatedCallableAddReplaceWith")
+@Deprecated(
+ "It was moved to androidx.lifecycle.viewmodel.compose package. You should add a " +
+ "dependency on androidx.lifecycle:lifecycle-viewmodel.compose:1.0.0-alpha01 in order to " +
+ "use it"
+)
val LocalViewModelStoreOwner = staticCompositionLocalOf<ViewModelStoreOwner>()
@Composable
@@ -190,6 +197,7 @@
LocalSavedStateRegistryOwner provides viewTreeOwners.savedStateRegistryOwner,
LocalSaveableStateRegistry provides saveableStateRegistry,
LocalView provides owner.view,
+ @Suppress("DEPRECATION")
LocalViewModelStoreOwner provides viewTreeOwners.viewModelStoreOwner
) {
ProvideCommonCompositionLocals(
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/res/PainterResources.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/res/PainterResources.kt
index e2b2e26f..b880f9a 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/res/PainterResources.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/res/PainterResources.kt
@@ -25,7 +25,7 @@
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.graphics.imageFromResource
-import androidx.compose.ui.graphics.painter.ImagePainter
+import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
@@ -35,7 +35,7 @@
/**
* Create a [Painter] from an Android resource id. This can load either an instance of
- * [ImagePainter] or [VectorPainter] for [ImageBitmap] based assets or vector based assets
+ * [BitmapPainter] or [VectorPainter] for [ImageBitmap] based assets or vector based assets
* respectively. The resources with the given id must point to either fully rasterized
* images (ex. PNG or JPG files) or VectorDrawable xml assets. API based xml Drawables
* are not supported here.
@@ -71,7 +71,7 @@
val imageBitmap = remember(path, id) {
loadImageBitmapResource(res, id)
}
- ImagePainter(imageBitmap)
+ BitmapPainter(imageBitmap)
}
}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/ViewModel.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/ViewModel.kt
index 5e8c29794..cb6f4ca 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/ViewModel.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/ViewModel.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:Suppress("DeprecatedCallableAddReplaceWith", "DEPRECATION")
+
package androidx.compose.ui.viewinterop
import androidx.compose.runtime.Composable
@@ -34,6 +36,11 @@
* @return A [ViewModel] that is an instance of the given [T] type.
*/
@Composable
+@Deprecated(
+ "It was moved to androidx.lifecycle.viewmodel.compose package. You should add a " +
+ "dependency on androidx.lifecycle:lifecycle-viewmodel.compose:1.0.0-alpha01 in order to " +
+ "use it"
+)
inline fun <reified T : ViewModel> viewModel(
key: String? = null,
factory: ViewModelProvider.Factory? = null
@@ -53,6 +60,11 @@
* @return A [ViewModel] that is an instance of the given [T] type.
*/
@Composable
+@Deprecated(
+ "It was moved to androidx.lifecycle.viewmodel.compose package. You should add a " +
+ "dependency on androidx.lifecycle:lifecycle-viewmodel.compose:1.0.0-alpha01 in order to " +
+ "use it"
+)
fun <T : ViewModel> viewModel(
modelClass: Class<T>,
key: String? = null,
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOrderModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOrderModifier.kt
index 8c530b6..dbd306d 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOrderModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOrderModifier.kt
@@ -112,6 +112,12 @@
}
/**
+ * A modifier that lets you specify a [FocusRequester] for the current composable so that this
+ * [focusRequester] can be used by another composable to specify a custom focus order.
+ */
+fun Modifier.focusOrder(focusRequester: FocusRequester): Modifier = focusRequester(focusRequester)
+
+/**
* A modifier that lets you specify a [FocusRequester] for the current composable along with
* [focusOrder].
*/
diff --git a/docs-tip-of-tree/build.gradle b/docs-tip-of-tree/build.gradle
index 9f96bb1..2062f2b 100644
--- a/docs-tip-of-tree/build.gradle
+++ b/docs-tip-of-tree/build.gradle
@@ -140,6 +140,7 @@
docs(project(":lifecycle:lifecycle-runtime-testing"))
docs(project(":lifecycle:lifecycle-service"))
docs(project(":lifecycle:lifecycle-viewmodel"))
+ docs(project(":lifecycle:lifecycle-viewmodel-compose"))
docs(project(":lifecycle:lifecycle-viewmodel-ktx"))
docs(project(":lifecycle:lifecycle-viewmodel-savedstate"))
docs(project(":loader:loader"))
diff --git a/lifecycle/lifecycle-viewmodel-compose/api/current.txt b/lifecycle/lifecycle-viewmodel-compose/api/current.txt
new file mode 100644
index 0000000..72357ec
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-compose/api/current.txt
@@ -0,0 +1,17 @@
+// Signature format: 4.0
+package androidx.lifecycle.viewmodel.compose {
+
+ public final class LocalViewModelStoreOwner {
+ method public androidx.compose.runtime.ProvidableCompositionLocal<androidx.lifecycle.ViewModelStoreOwner> asProvidableCompositionLocal();
+ method @androidx.compose.runtime.Composable public androidx.lifecycle.ViewModelStoreOwner getCurrent();
+ property @androidx.compose.runtime.Composable public final androidx.lifecycle.ViewModelStoreOwner current;
+ field public static final androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner INSTANCE;
+ }
+
+ public final class ViewModelKt {
+ method @androidx.compose.runtime.Composable public static <T extends androidx.lifecycle.ViewModel> T viewModel(Class<T> modelClass, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ method @androidx.compose.runtime.Composable public static inline <reified T extends androidx.lifecycle.ViewModel> T! viewModel(optional String key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ }
+
+}
+
diff --git a/lifecycle/lifecycle-viewmodel-compose/api/public_plus_experimental_current.txt b/lifecycle/lifecycle-viewmodel-compose/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..72357ec
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-compose/api/public_plus_experimental_current.txt
@@ -0,0 +1,17 @@
+// Signature format: 4.0
+package androidx.lifecycle.viewmodel.compose {
+
+ public final class LocalViewModelStoreOwner {
+ method public androidx.compose.runtime.ProvidableCompositionLocal<androidx.lifecycle.ViewModelStoreOwner> asProvidableCompositionLocal();
+ method @androidx.compose.runtime.Composable public androidx.lifecycle.ViewModelStoreOwner getCurrent();
+ property @androidx.compose.runtime.Composable public final androidx.lifecycle.ViewModelStoreOwner current;
+ field public static final androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner INSTANCE;
+ }
+
+ public final class ViewModelKt {
+ method @androidx.compose.runtime.Composable public static <T extends androidx.lifecycle.ViewModel> T viewModel(Class<T> modelClass, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ method @androidx.compose.runtime.Composable public static inline <reified T extends androidx.lifecycle.ViewModel> T! viewModel(optional String key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ }
+
+}
+
diff --git a/lifecycle/lifecycle-viewmodel-compose/api/res-current.txt b/lifecycle/lifecycle-viewmodel-compose/api/res-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-compose/api/res-current.txt
diff --git a/lifecycle/lifecycle-viewmodel-compose/api/restricted_current.txt b/lifecycle/lifecycle-viewmodel-compose/api/restricted_current.txt
new file mode 100644
index 0000000..72357ec
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-compose/api/restricted_current.txt
@@ -0,0 +1,17 @@
+// Signature format: 4.0
+package androidx.lifecycle.viewmodel.compose {
+
+ public final class LocalViewModelStoreOwner {
+ method public androidx.compose.runtime.ProvidableCompositionLocal<androidx.lifecycle.ViewModelStoreOwner> asProvidableCompositionLocal();
+ method @androidx.compose.runtime.Composable public androidx.lifecycle.ViewModelStoreOwner getCurrent();
+ property @androidx.compose.runtime.Composable public final androidx.lifecycle.ViewModelStoreOwner current;
+ field public static final androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner INSTANCE;
+ }
+
+ public final class ViewModelKt {
+ method @androidx.compose.runtime.Composable public static <T extends androidx.lifecycle.ViewModel> T viewModel(Class<T> modelClass, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ method @androidx.compose.runtime.Composable public static inline <reified T extends androidx.lifecycle.ViewModel> T! viewModel(optional String key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ }
+
+}
+
diff --git a/lifecycle/lifecycle-viewmodel-compose/build.gradle b/lifecycle/lifecycle-viewmodel-compose/build.gradle
new file mode 100644
index 0000000..a89b2a0
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-compose/build.gradle
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+import androidx.build.Publish
+import androidx.build.RunApiTasks
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+import static androidx.build.dependencies.DependenciesKt.*
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.library")
+ id("AndroidXUiPlugin")
+ id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+ kotlinPlugin projectOrArtifact(":compose:compiler:compiler")
+
+ api "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.0"
+ api projectOrArtifact(":compose:runtime:runtime")
+ api projectOrArtifact(":compose:ui:ui")
+
+ implementation(KOTLIN_STDLIB)
+
+ androidTestImplementation projectOrArtifact(":compose:ui:ui-test-junit4")
+ androidTestImplementation(ANDROIDX_TEST_RULES)
+ androidTestImplementation(ANDROIDX_TEST_RUNNER)
+ androidTestImplementation(JUNIT)
+ androidTestImplementation(TRUTH)
+ androidTestImplementation "androidx.fragment:fragment:1.2.4"
+ androidTestImplementation "androidx.appcompat:appcompat:1.1.0"
+ androidTestImplementation projectOrArtifact(":activity:activity-compose")
+}
+
+androidx {
+ name = "Lifecycle ViewModel Compose"
+ publish = Publish.SNAPSHOT_AND_RELEASE
+ mavenVersion = LibraryVersions.LIFECYCLE_COMPOSE
+ mavenGroup = LibraryGroups.LIFECYCLE
+ inceptionYear = "2021"
+ description = "Compose integration with Lifecycle ViewModel"
+ runApiTasks = new RunApiTasks.Yes()
+}
diff --git a/lifecycle/lifecycle-viewmodel-compose/integration-tests/lifecycle-viewmodel-demos/build.gradle b/lifecycle/lifecycle-viewmodel-compose/integration-tests/lifecycle-viewmodel-demos/build.gradle
new file mode 100644
index 0000000..8979c3c
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-compose/integration-tests/lifecycle-viewmodel-demos/build.gradle
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import androidx.build.Publish
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+import static androidx.build.dependencies.DependenciesKt.getKOTLIN_STDLIB
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.library")
+ id("AndroidXUiPlugin")
+ id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+ kotlinPlugin projectOrArtifact(":compose:compiler:compiler")
+ implementation(KOTLIN_STDLIB)
+ implementation projectOrArtifact(":lifecycle:lifecycle-viewmodel-compose")
+ implementation projectOrArtifact(
+ ":lifecycle:lifecycle-viewmodel-compose:lifecycle-viewmodel-compose-samples"
+ )
+}
+
+androidx {
+ name = "Compose Lifecycle ViewModel Demos"
+ publish = Publish.NONE
+ inceptionYear = "2021"
+ description = "This is a project for Lifecycle ViewModel demos."
+}
diff --git a/lifecycle/lifecycle-viewmodel-compose/integration-tests/lifecycle-viewmodel-demos/src/main/AndroidManifest.xml b/lifecycle/lifecycle-viewmodel-compose/integration-tests/lifecycle-viewmodel-demos/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..d9d8620
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-compose/integration-tests/lifecycle-viewmodel-demos/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<manifest package="androidx.lifecycle.viewmodel.compose.demos" />
diff --git a/lifecycle/lifecycle-viewmodel-compose/samples/build.gradle b/lifecycle/lifecycle-viewmodel-compose/samples/build.gradle
new file mode 100644
index 0000000..3f1d512
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-compose/samples/build.gradle
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+import androidx.build.LibraryType
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+import static androidx.build.dependencies.DependenciesKt.*
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.library")
+ id("AndroidXUiPlugin")
+ id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+ kotlinPlugin projectOrArtifact(":compose:compiler:compiler")
+ implementation(KOTLIN_STDLIB)
+ implementation projectOrArtifact(":lifecycle:lifecycle-viewmodel-compose")
+}
+
+androidx {
+ name = "AndroidX Lifecycle ViewModel Compose Integration Samples"
+ type = LibraryType.SAMPLES
+ mavenVersion = LibraryVersions.LIFECYCLE
+ mavenGroup = LibraryGroups.LIFECYCLE
+ inceptionYear = "2021"
+ description = "Samples for Compose integration with Lifecycle ViewModel"
+}
diff --git a/lifecycle/lifecycle-viewmodel-compose/samples/src/main/AndroidManifest.xml b/lifecycle/lifecycle-viewmodel-compose/samples/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..26af120
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-compose/samples/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<manifest package="androidx.lifecycle.viewmodel.compose.samples" />
diff --git a/lifecycle/lifecycle-viewmodel-compose/src/androidTest/AndroidManifest.xml b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000..6de27ab
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="androidx.lifecycle.viewmodel.compose">
+
+ <application>
+ <activity
+ android:name="androidx.appcompat.app.AppCompatActivity"
+ android:theme="@style/Theme.AppCompat" />
+ <activity android:name="androidx.fragment.app.FragmentActivity" />
+ </application>
+</manifest>
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/TestViewModelClasses.kt b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/TestViewModelClasses.kt
similarity index 68%
rename from compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/TestViewModelClasses.kt
rename to lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/TestViewModelClasses.kt
index 1c56197..e8f0678 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/TestViewModelClasses.kt
+++ b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/TestViewModelClasses.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,28 +14,29 @@
* limitations under the License.
*/
-package androidx.compose.ui.viewinterop
+package androidx.lifecycle.viewmodel.compose
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
-val viewModelClasses = arrayOf(
+public val viewModelClasses: Array<Class<out ViewModel>> = arrayOf(
SimpleViewModel::class.java,
ApplicationViewModel::class.java,
SavedStateHandleViewModel::class.java,
SavedStateHandleAndApplicationViewModel::class.java
)
-class SimpleViewModel : ViewModel()
+public class SimpleViewModel : ViewModel()
-class SavedStateHandleViewModel(@Suppress("UNUSED_PARAMETER") savedStateHandle: SavedStateHandle) :
- ViewModel()
+public class SavedStateHandleViewModel(
+ @Suppress("UNUSED_PARAMETER") savedStateHandle: SavedStateHandle
+) : ViewModel()
-class ApplicationViewModel(application: Application) : AndroidViewModel(application)
+public class ApplicationViewModel(application: Application) : AndroidViewModel(application)
-class SavedStateHandleAndApplicationViewModel(
+public class SavedStateHandleAndApplicationViewModel(
application: Application,
@Suppress("UNUSED_PARAMETER") savedStateHandle: SavedStateHandle
) : AndroidViewModel(application)
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/ViewModelInAppCompatActivityTest.kt b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInAppCompatActivityTest.kt
similarity index 82%
rename from compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/ViewModelInAppCompatActivityTest.kt
rename to lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInAppCompatActivityTest.kt
index 6e5fa84..7681326 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/ViewModelInAppCompatActivityTest.kt
+++ b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInAppCompatActivityTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.compose.ui.viewinterop
+package androidx.lifecycle.viewmodel.compose
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
@@ -34,21 +34,20 @@
@MediumTest
@RunWith(AndroidJUnit4::class)
-class ViewModelInAppCompatActivityTest {
+public class ViewModelInAppCompatActivityTest {
@Suppress("DEPRECATION")
@get:Rule
- val activityTestRule = androidx.test.rule.ActivityTestRule<AppCompatActivity>(
- AppCompatActivity::class.java
- )
+ public val activityTestRule: androidx.test.rule.ActivityTestRule<AppCompatActivity> =
+ androidx.test.rule.ActivityTestRule(AppCompatActivity::class.java)
private lateinit var activity: AppCompatActivity
@Before
- fun setup() {
+ public fun setup() {
activity = activityTestRule.activity
}
@Test
- fun lifecycleOwnerIsAvailable() {
+ public fun lifecycleOwnerIsAvailable() {
val latch = CountDownLatch(1)
var owner: LifecycleOwner? = null
@@ -64,7 +63,7 @@
}
@Test
- fun lifecycleOwnerIsAvailableWhenComposedIntoViewGroup() {
+ public fun lifecycleOwnerIsAvailableWhenComposedIntoViewGroup() {
val latch = CountDownLatch(1)
var owner: LifecycleOwner? = null
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/ViewModelInComponentActivityTest.kt b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInComponentActivityTest.kt
similarity index 82%
rename from compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/ViewModelInComponentActivityTest.kt
rename to lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInComponentActivityTest.kt
index 10b603a..fbc90b5 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/ViewModelInComponentActivityTest.kt
+++ b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInComponentActivityTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.compose.ui.viewinterop
+package androidx.lifecycle.viewmodel.compose
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
@@ -34,21 +34,20 @@
@MediumTest
@RunWith(AndroidJUnit4::class)
-class ViewModelInComponentActivityTest {
+public class ViewModelInComponentActivityTest {
@Suppress("DEPRECATION")
@get:Rule
- val activityTestRule = androidx.test.rule.ActivityTestRule<ComponentActivity>(
- ComponentActivity::class.java
- )
+ public val activityTestRule: androidx.test.rule.ActivityTestRule<ComponentActivity> =
+ androidx.test.rule.ActivityTestRule(ComponentActivity::class.java)
private lateinit var activity: ComponentActivity
@Before
- fun setup() {
+ public fun setup() {
activity = activityTestRule.activity
}
@Test
- fun lifecycleOwnerIsAvailable() {
+ public fun lifecycleOwnerIsAvailable() {
val latch = CountDownLatch(1)
var owner: LifecycleOwner? = null
@@ -64,7 +63,7 @@
}
@Test
- fun lifecycleOwnerIsAvailableWhenComposedIntoViewGroup() {
+ public fun lifecycleOwnerIsAvailableWhenComposedIntoViewGroup() {
val latch = CountDownLatch(1)
var owner: LifecycleOwner? = null
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/ViewModelInFragmentTest.kt b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInFragmentTest.kt
similarity index 73%
rename from compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/ViewModelInFragmentTest.kt
rename to lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInFragmentTest.kt
index 64a7db0..a6ba005 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/ViewModelInFragmentTest.kt
+++ b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInFragmentTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.compose.ui.viewinterop
+package androidx.lifecycle.viewmodel.compose
import android.os.Bundle
import android.view.LayoutInflater
@@ -23,7 +23,6 @@
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentContainerView
-import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import androidx.test.filters.MediumTest
import org.junit.Assert.assertTrue
@@ -37,28 +36,27 @@
@MediumTest
@RunWith(Parameterized::class)
-class ViewModelInFragmentTest(private val viewModelClass: Class<out ViewModel>) {
+public class ViewModelInFragmentTest(private val viewModelClass: Class<out ViewModel>) {
- companion object {
+ public companion object {
@JvmStatic
@Parameterized.Parameters(name = "{0}")
- fun initParameters() = viewModelClasses
+ public fun initParameters(): Array<Class<out ViewModel>> = viewModelClasses
}
@Suppress("DEPRECATION")
@get:Rule
- val activityTestRule = androidx.test.rule.ActivityTestRule<FragmentActivity>(
- FragmentActivity::class.java
- )
+ public val activityTestRule: androidx.test.rule.ActivityTestRule<FragmentActivity> =
+ androidx.test.rule.ActivityTestRule(FragmentActivity::class.java)
private lateinit var activity: FragmentActivity
@Before
- fun setup() {
+ public fun setup() {
activity = activityTestRule.activity
}
@Test
- fun viewModelCreatedInFragment() {
+ public fun viewModelCreatedInFragment() {
val fragment = TestFragment(viewModelClass)
activityTestRule.runOnUiThread {
@@ -74,16 +72,15 @@
}
}
-class TestFragment(private val viewModelClass: Class<out ViewModel>) : Fragment() {
+public class TestFragment(private val viewModelClass: Class<out ViewModel>) : Fragment() {
- var owner: LifecycleOwner? = null
- val latch = CountDownLatch(1)
+ public val latch: CountDownLatch = CountDownLatch(1)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
- ) = ComposeView(requireContext()).apply {
+ ): ComposeView = ComposeView(requireContext()).apply {
setContent {
viewModel(viewModelClass)
latch.countDown()
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/ViewModelTest.kt b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelTest.kt
similarity index 73%
rename from compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/ViewModelTest.kt
rename to lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelTest.kt
index 4347258..ce0e504 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/ViewModelTest.kt
+++ b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package androidx.compose.ui.viewinterop
+package androidx.lifecycle.viewmodel.compose
import androidx.compose.runtime.Providers
-import androidx.compose.ui.platform.LocalViewModelStoreOwner
+import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.lifecycle.HasDefaultViewModelProviderFactory
import androidx.lifecycle.ViewModel
@@ -33,16 +33,16 @@
@MediumTest
@RunWith(AndroidJUnit4::class)
-class ViewModelTest {
+public class ViewModelTest {
@get:Rule
- val rule = createComposeRule()
+ public val rule: ComposeContentTestRule = createComposeRule()
@Test
- fun viewModelCreatedViaDefaultFactory() {
+ public fun viewModelCreatedViaDefaultFactory() {
val owner = FakeViewModelStoreOwner()
rule.setContent {
- Providers(LocalViewModelStoreOwner provides owner) {
+ Providers(LocalViewModelStoreOwner.asProvidableCompositionLocal() provides owner) {
viewModel<TestViewModel>()
}
}
@@ -51,11 +51,11 @@
}
@Test
- fun viewModelCreatedViaDefaultFactoryWithKey() {
+ public fun viewModelCreatedViaDefaultFactoryWithKey() {
val owner = FakeViewModelStoreOwner()
var createdInComposition: Any? = null
rule.setContent {
- Providers(LocalViewModelStoreOwner provides owner) {
+ Providers(LocalViewModelStoreOwner.asProvidableCompositionLocal() provides owner) {
createdInComposition = viewModel<TestViewModel>()
}
}
@@ -66,11 +66,11 @@
}
@Test
- fun createdViewModelIsEqualsToCreatedManually() {
+ public fun createdViewModelIsEqualsToCreatedManually() {
val owner = FakeViewModelStoreOwner()
var createdInComposition: Any? = null
rule.setContent {
- Providers(LocalViewModelStoreOwner provides owner) {
+ Providers(LocalViewModelStoreOwner.asProvidableCompositionLocal() provides owner) {
createdInComposition = viewModel<TestViewModel>()
}
}
@@ -81,12 +81,13 @@
}
@Test
- fun createdViewModelIsEqualsToCreatedManuallyWithKey() {
+ public fun createdViewModelIsEqualsToCreatedManuallyWithKey() {
val owner = FakeViewModelStoreOwner()
var createdInComposition: Any? = null
rule.setContent {
- Providers(LocalViewModelStoreOwner provides owner) {
- createdInComposition = viewModel<TestViewModel>(key = "test")
+ Providers(LocalViewModelStoreOwner.asProvidableCompositionLocal() provides owner) {
+ createdInComposition =
+ viewModel<TestViewModel>(key = "test")
}
}
@@ -96,11 +97,11 @@
}
@Test
- fun customFactoryIsUsedWhenProvided() {
+ public fun customFactoryIsUsedWhenProvided() {
val owner = FakeViewModelStoreOwner()
val customFactory = FakeViewModelProviderFactory()
rule.setContent {
- Providers(LocalViewModelStoreOwner provides owner) {
+ Providers(LocalViewModelStoreOwner.asProvidableCompositionLocal() provides owner) {
viewModel<TestViewModel>(factory = customFactory)
}
}
@@ -109,11 +110,11 @@
}
@Test
- fun defaultFactoryIsNotUsedWhenCustomProvided() {
+ public fun defaultFactoryIsNotUsedWhenCustomProvided() {
val owner = FakeViewModelStoreOwner()
val customFactory = FakeViewModelProviderFactory()
rule.setContent {
- Providers(LocalViewModelStoreOwner provides owner) {
+ Providers(LocalViewModelStoreOwner.asProvidableCompositionLocal() provides owner) {
viewModel<TestViewModel>(factory = customFactory)
}
}
@@ -122,12 +123,12 @@
}
@Test
- fun createdWithCustomFactoryViewModelIsEqualsToCreatedManually() {
+ public fun createdWithCustomFactoryViewModelIsEqualsToCreatedManually() {
val owner = FakeViewModelStoreOwner()
var createdInComposition: Any? = null
val customFactory = FakeViewModelProviderFactory()
rule.setContent {
- Providers(LocalViewModelStoreOwner provides owner) {
+ Providers(LocalViewModelStoreOwner.asProvidableCompositionLocal() provides owner) {
createdInComposition = viewModel<TestViewModel>()
}
}
@@ -138,13 +139,14 @@
}
@Test
- fun createdWithCustomFactoryViewModelIsEqualsToCreatedManuallyWithKey() {
+ public fun createdWithCustomFactoryViewModelIsEqualsToCreatedManuallyWithKey() {
val owner = FakeViewModelStoreOwner()
var createdInComposition: Any? = null
val customFactory = FakeViewModelProviderFactory()
rule.setContent {
- Providers(LocalViewModelStoreOwner provides owner) {
- createdInComposition = viewModel<TestViewModel>(key = "test")
+ Providers(LocalViewModelStoreOwner.asProvidableCompositionLocal() provides owner) {
+ createdInComposition =
+ viewModel<TestViewModel>(key = "test")
}
}
@@ -173,4 +175,4 @@
override fun getViewModelStore(): ViewModelStore = store
override fun getDefaultViewModelProviderFactory(): ViewModelProvider.Factory = factory
-}
\ No newline at end of file
+}
diff --git a/lifecycle/lifecycle-viewmodel-compose/src/main/AndroidManifest.xml b/lifecycle/lifecycle-viewmodel-compose/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..33022bf
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-compose/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<manifest package="androidx.lifecycle.viewmodel.compose" />
diff --git a/lifecycle/lifecycle-viewmodel-compose/src/main/java/androidx/lifecycle/viewmodel/compose/LocalViewModelStoreOwner.kt b/lifecycle/lifecycle-viewmodel-compose/src/main/java/androidx/lifecycle/viewmodel/compose/LocalViewModelStoreOwner.kt
new file mode 100644
index 0000000..c3ea604
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-compose/src/main/java/androidx/lifecycle/viewmodel/compose/LocalViewModelStoreOwner.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.lifecycle.viewmodel.compose
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ProvidableCompositionLocal
+import androidx.compose.runtime.compositionLocalOf
+import androidx.compose.ui.platform.LocalView
+import androidx.lifecycle.ViewModelStoreOwner
+import androidx.lifecycle.ViewTreeViewModelStoreOwner
+
+/**
+ * The CompositionLocal containing the current [ViewModelStoreOwner].
+ */
+public object LocalViewModelStoreOwner {
+ private val LocalViewModelStoreOwner =
+ compositionLocalOf<ViewModelStoreOwner?> { null }
+
+ /**
+ * Returns current composition local value for the owner.
+ */
+ public val current: ViewModelStoreOwner
+ @Composable
+ get() = LocalViewModelStoreOwner.current
+ ?: ViewTreeViewModelStoreOwner.get(LocalView.current)
+ ?: error("No ViewModelStoreOwner provided")
+
+ /**
+ * Returns a [ProvidableCompositionLocal] which you can use to override the value for the
+ * subtree.
+ */
+ public fun asProvidableCompositionLocal():
+ ProvidableCompositionLocal<ViewModelStoreOwner?> = LocalViewModelStoreOwner
+}
diff --git a/lifecycle/lifecycle-viewmodel-compose/src/main/java/androidx/lifecycle/viewmodel/compose/ViewModel.kt b/lifecycle/lifecycle-viewmodel-compose/src/main/java/androidx/lifecycle/viewmodel/compose/ViewModel.kt
new file mode 100644
index 0000000..3166d7f
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-compose/src/main/java/androidx/lifecycle/viewmodel/compose/ViewModel.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.lifecycle.viewmodel.compose
+
+import androidx.compose.runtime.Composable
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.ViewModelStoreOwner
+
+/**
+ * Returns an existing [ViewModel] or creates a new one in the scope (usually, a fragment or
+ * an activity)
+ *
+ * The created [ViewModel] is associated with the given scope and will be retained
+ * as long as the scope is alive (e.g. if it is an activity, until it is
+ * finished or process is killed).
+ *
+ * @param key The key to use to identify the [ViewModel].
+ * @return A [ViewModel] that is an instance of the given [T] type.
+ */
+@Suppress("MissingJvmstatic")
+@Composable
+public inline fun <reified T : ViewModel> viewModel(
+ key: String? = null,
+ factory: ViewModelProvider.Factory? = null
+): T = viewModel(T::class.java, key, factory)
+
+/**
+ * Returns an existing [ViewModel] or creates a new one in the scope (usually, a fragment or
+ * an activity)
+ *
+ * The created [ViewModel] is associated with the given scope and will be retained
+ * as long as the scope is alive (e.g. if it is an activity, until it is
+ * finished or process is killed).
+ *
+ * @param modelClass The class of the [ViewModel] to create an instance of it if it is not
+ * present.
+ * @param key The key to use to identify the [ViewModel].
+ * @return A [ViewModel] that is an instance of the given [T] type.
+ */
+@Suppress("MissingJvmstatic")
+@Composable
+public fun <T : ViewModel> viewModel(
+ modelClass: Class<T>,
+ key: String? = null,
+ factory: ViewModelProvider.Factory? = null
+): T = LocalViewModelStoreOwner.current.get(modelClass, key, factory)
+
+private fun <T : ViewModel> ViewModelStoreOwner.get(
+ javaClass: Class<T>,
+ key: String? = null,
+ factory: ViewModelProvider.Factory? = null
+): T {
+ val provider = if (factory != null) {
+ ViewModelProvider(this, factory)
+ } else {
+ ViewModelProvider(this)
+ }
+ return if (key != null) {
+ provider.get(key, javaClass)
+ } else {
+ provider.get(javaClass)
+ }
+}
diff --git a/navigation/navigation-compose/build.gradle b/navigation/navigation-compose/build.gradle
index 9de1beb..5a4779d 100644
--- a/navigation/navigation-compose/build.gradle
+++ b/navigation/navigation-compose/build.gradle
@@ -35,6 +35,7 @@
api projectOrArtifact(":compose:runtime:runtime")
api projectOrArtifact(":compose:runtime:runtime-saveable")
api projectOrArtifact(":compose:ui:ui")
+ api projectOrArtifact(":lifecycle:lifecycle-viewmodel-compose")
api "androidx.navigation:navigation-runtime-ktx:2.3.1"
androidTestImplementation projectOrArtifact(":compose:material:material")
diff --git a/navigation/navigation-compose/src/main/java/androidx/navigation/compose/NavHost.kt b/navigation/navigation-compose/src/main/java/androidx/navigation/compose/NavHost.kt
index 166dbec..d999432 100644
--- a/navigation/navigation-compose/src/main/java/androidx/navigation/compose/NavHost.kt
+++ b/navigation/navigation-compose/src/main/java/androidx/navigation/compose/NavHost.kt
@@ -26,10 +26,10 @@
import androidx.compose.runtime.saveable.rememberSaveableStateHolder
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
-import androidx.compose.ui.platform.LocalViewModelStoreOwner
-import androidx.compose.ui.viewinterop.viewModel
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
+import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavGraph
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
@@ -124,7 +124,11 @@
// while in the scope of the composable, we provide the navBackStackEntry as the
// ViewModelStoreOwner and LifecycleOwner
Providers(
- LocalViewModelStoreOwner provides currentNavBackStackEntry,
+ LocalViewModelStoreOwner.asProvidableCompositionLocal()
+ provides currentNavBackStackEntry,
+ @Suppress("DEPRECATION") // To be removed when we remove the one from compose:ui
+ androidx.compose.ui.platform.LocalViewModelStoreOwner provides
+ currentNavBackStackEntry,
LocalLifecycleOwner provides currentNavBackStackEntry
) {
saveableStateHolder.SaveableStateProvider {
diff --git a/settings.gradle b/settings.gradle
index d5acbe5..09af826 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -370,6 +370,9 @@
includeProject(":lifecycle:lifecycle-runtime-testing", "lifecycle/lifecycle-runtime-testing", [BuildType.MAIN, BuildType.FLAN])
includeProject(":lifecycle:lifecycle-service", "lifecycle/lifecycle-service", [BuildType.MAIN, BuildType.FLAN])
includeProject(":lifecycle:lifecycle-viewmodel", "lifecycle/lifecycle-viewmodel", [BuildType.MAIN, BuildType.FLAN])
+includeProject(":lifecycle:lifecycle-viewmodel-compose", "lifecycle/lifecycle-viewmodel-compose", [BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-viewmodel-compose:lifecycle-viewmodel-compose-samples", "lifecycle/lifecycle-viewmodel-compose/samples", [BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-viewmodel-compose:integration-tests:lifecycle-viewmodel-demos", "lifecycle/lifecycle-viewmodel-compose/integration-tests/lifecycle-viewmodel-demos", [BuildType.COMPOSE])
includeProject(":lifecycle:lifecycle-viewmodel-ktx", "lifecycle/lifecycle-viewmodel-ktx", [BuildType.MAIN, BuildType.FLAN])
includeProject(":lifecycle:lifecycle-viewmodel-savedstate", "lifecycle/lifecycle-viewmodel-savedstate", [BuildType.MAIN, BuildType.FLAN])
includeProject(":lint-checks", "lint-checks")
diff --git a/window/window/src/main/java/androidx/window/ExtensionWindowBackend.java b/window/window/src/main/java/androidx/window/ExtensionWindowBackend.java
index d197992..2fa539f 100644
--- a/window/window/src/main/java/androidx/window/ExtensionWindowBackend.java
+++ b/window/window/src/main/java/androidx/window/ExtensionWindowBackend.java
@@ -200,6 +200,7 @@
if (DEBUG) {
Log.v(TAG, "Extension not loaded, skipping callback registration.");
}
+ callback.accept(new WindowLayoutInfo(new ArrayList<>()));
return;
}
diff --git a/window/window/src/test/java/androidx/window/ExtensionWindowBackendUnitTest.java b/window/window/src/test/java/androidx/window/ExtensionWindowBackendUnitTest.java
index b79864f..76727e9 100644
--- a/window/window/src/test/java/androidx/window/ExtensionWindowBackendUnitTest.java
+++ b/window/window/src/test/java/androidx/window/ExtensionWindowBackendUnitTest.java
@@ -23,7 +23,6 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -73,7 +72,7 @@
public void testRegisterDeviceStateChangeCallback_noExtension() {
// Verify method with extension
ExtensionWindowBackend backend = ExtensionWindowBackend.getInstance(mContext);
- assumeTrue(backend.mWindowExtension == null);
+ backend.mWindowExtension = null;
SimpleConsumer<DeviceState> simpleConsumer = new SimpleConsumer<>();
backend.registerDeviceStateChangeCallback(directExecutor(), simpleConsumer);
@@ -117,6 +116,19 @@
}
@Test
+ public void testRegisterLayoutChangeCallback_noExtension() {
+ ExtensionWindowBackend backend = ExtensionWindowBackend.getInstance(mContext);
+ backend.mWindowExtension = null;
+
+ // Check registering the layout change callback
+ Consumer<WindowLayoutInfo> consumer = mock(WindowLayoutInfoConsumer.class);
+ Activity activity = mock(Activity.class);
+ backend.registerLayoutChangeCallback(activity, Runnable::run, consumer);
+
+ verify(consumer).accept(any());
+ }
+
+ @Test
public void testRegisterLayoutChangeCallback_synchronousExtension() {
WindowLayoutInfo expectedInfo = newTestWindowLayoutInfo();
ExtensionInterfaceCompat extensionInterfaceCompat =