Merge "Date picker input mode validation error height" into androidx-main
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/DateInputTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/DateInputTest.kt
index b857ce6..b2ce6f2 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/DateInputTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/DateInputTest.kt
@@ -20,17 +20,23 @@
import androidx.compose.material3.internal.Strings
import androidx.compose.material3.internal.formatWithSkeleton
import androidx.compose.material3.internal.getString
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.SemanticsProperties
import androidx.compose.ui.test.SemanticsMatcher.Companion.expectValue
import androidx.compose.ui.test.SemanticsMatcher.Companion.keyIsDefined
import androidx.compose.ui.test.assert
import androidx.compose.ui.test.assertContentDescriptionEquals
import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.assertIsEqualTo
+import androidx.compose.ui.test.getBoundsInRoot
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
+import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
+import androidx.compose.ui.unit.height
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import androidx.test.filters.SdkSuppress
@@ -228,6 +234,29 @@
}
@Test
+ fun heightUnchangedWithError() {
+ lateinit var dateInputLabel: String
+ rule.setMaterialContent(lightColorScheme()) {
+ dateInputLabel = getString(string = Strings.DateInputLabel)
+ DatePicker(
+ state = rememberDatePickerState(initialDisplayMode = DisplayMode.Input),
+ modifier = Modifier.testTag(DateInputTestTag)
+ )
+ }
+ val withoutErrorBounds = rule.onNodeWithTag(DateInputTestTag).getBoundsInRoot()
+ // Type a date that will trigger an error text.
+ rule.onNodeWithText(dateInputLabel).performClick().performTextInput("12123000")
+ rule.waitForIdle()
+ val withErrorBounds = rule.onNodeWithTag(DateInputTestTag).getBoundsInRoot()
+
+ // Check that the height of the component did not change after having the error text visible
+ withoutErrorBounds.height.assertIsEqualTo(
+ withErrorBounds.height,
+ subject = "Date input height"
+ )
+ }
+
+ @Test
fun defaultSemantics() {
val selectedDateInUtcMillis = dayInUtcMilliseconds(year = 2010, month = 5, dayOfMonth = 11)
lateinit var expectedHeadlineStringFormat: String
@@ -268,4 +297,6 @@
firstDayCalendar[Calendar.DAY_OF_MONTH] = dayOfMonth
return firstDayCalendar.timeInMillis
}
+
+ private val DateInputTestTag = "DateInput"
}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateInput.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateInput.kt
index 4af5390..ddaa0c4 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateInput.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateInput.kt
@@ -138,6 +138,17 @@
)
}
+ // Calculate how much bottom padding should be added. In case there is an error text, which is
+ // added as a supportingText, take into account the default supportingText padding to ensure
+ // the padding does not trigger a component height change.
+ val bottomPadding =
+ if (errorText.value.isBlank()) {
+ InputTextNonErroneousBottomPadding
+ } else {
+ val textFieldPadding = TextFieldDefaults.supportingTextPadding()
+ InputTextNonErroneousBottomPadding -
+ (textFieldPadding.calculateBottomPadding() + textFieldPadding.calculateTopPadding())
+ }
OutlinedTextField(
value = text,
onValueChange = { input ->
@@ -175,18 +186,9 @@
}
},
modifier =
- modifier
- // Add bottom padding when there is no error. Otherwise, remove it as the error text
- // will take additional height.
- .padding(
- bottom =
- if (errorText.value.isNotBlank()) {
- 0.dp
- } else {
- InputTextNonErroneousBottomPadding
- }
- )
- .semantics { if (errorText.value.isNotBlank()) error(errorText.value) },
+ modifier.padding(bottom = bottomPadding).semantics {
+ if (errorText.value.isNotBlank()) error(errorText.value)
+ },
label = label,
placeholder = placeholder,
supportingText = { if (errorText.value.isNotBlank()) Text(errorText.value) },