1 /* <lambda>null2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.compose.material3 18 19 import androidx.annotation.FloatRange 20 import androidx.compose.animation.animateColorAsState 21 import androidx.compose.foundation.border 22 import androidx.compose.foundation.interaction.Interaction 23 import androidx.compose.foundation.interaction.InteractionSource 24 import androidx.compose.foundation.interaction.MutableInteractionSource 25 import androidx.compose.foundation.interaction.collectIsFocusedAsState 26 import androidx.compose.foundation.layout.Box 27 import androidx.compose.foundation.layout.PaddingValues 28 import androidx.compose.foundation.text.BasicTextField 29 import androidx.compose.foundation.text.input.OutputTransformation 30 import androidx.compose.foundation.text.input.TextFieldBuffer 31 import androidx.compose.foundation.text.input.TextFieldDecorator 32 import androidx.compose.foundation.text.input.TextFieldLineLimits 33 import androidx.compose.foundation.text.input.TextFieldLineLimits.MultiLine 34 import androidx.compose.foundation.text.input.TextFieldLineLimits.SingleLine 35 import androidx.compose.foundation.text.input.TextFieldState 36 import androidx.compose.foundation.text.selection.LocalTextSelectionColors 37 import androidx.compose.foundation.text.selection.TextSelectionColors 38 import androidx.compose.material3.internal.CommonDecorationBox 39 import androidx.compose.material3.internal.SupportingTopPadding 40 import androidx.compose.material3.internal.TextFieldPadding 41 import androidx.compose.material3.internal.TextFieldType 42 import androidx.compose.material3.internal.animateBorderStrokeAsState 43 import androidx.compose.material3.internal.textFieldBackground 44 import androidx.compose.material3.tokens.FilledTextFieldTokens 45 import androidx.compose.material3.tokens.MotionSchemeKeyTokens 46 import androidx.compose.material3.tokens.OutlinedTextFieldTokens 47 import androidx.compose.runtime.Composable 48 import androidx.compose.runtime.Immutable 49 import androidx.compose.runtime.Stable 50 import androidx.compose.runtime.remember 51 import androidx.compose.ui.Alignment 52 import androidx.compose.ui.Modifier 53 import androidx.compose.ui.graphics.Color 54 import androidx.compose.ui.graphics.Shape 55 import androidx.compose.ui.graphics.takeOrElse 56 import androidx.compose.ui.text.AnnotatedString 57 import androidx.compose.ui.text.input.VisualTransformation 58 import androidx.compose.ui.unit.Dp 59 import androidx.compose.ui.unit.dp 60 61 /** 62 * Contains the default values used by [TextField]. For defaults used in [OutlinedTextField], see 63 * [OutlinedTextFieldDefaults]. 64 */ 65 @Immutable 66 object TextFieldDefaults { 67 /** Default shape for a [TextField]. */ 68 val shape: Shape 69 @Composable get() = FilledTextFieldTokens.ContainerShape.value 70 71 /** 72 * The default min height applied to a [TextField]. Note that you can override it by applying 73 * Modifier.heightIn directly on a text field. 74 */ 75 val MinHeight = 56.dp 76 77 /** 78 * The default min width applied to a [TextField]. Note that you can override it by applying 79 * Modifier.widthIn directly on a text field. 80 */ 81 val MinWidth = 280.dp 82 83 /** The default thickness of the indicator line in [TextField] in unfocused state. */ 84 val UnfocusedIndicatorThickness = 1.dp 85 86 /** The default thickness of the indicator line in [TextField] in focused state. */ 87 val FocusedIndicatorThickness = 2.dp 88 89 /** 90 * A decorator used to create custom text fields based on 91 * [Material Design filled text field](https://m3.material.io/components/text-fields/overview). 92 * 93 * If your text field requires customising elements that aren't exposed by [TextField], such as 94 * the indicator line thickness, consider using this decorator to achieve the desired design. 95 * 96 * For example, if you wish to customise the bottom indicator line, you can pass a custom 97 * [Container] to this decorator's [container]. 98 * 99 * This decorator is meant to be used in conjunction with the overload of [BasicTextField] that 100 * accepts a [TextFieldDecorator] parameter. For other overloads of [BasicTextField] that use a 101 * `decorationBox`, see [DecorationBox]. 102 * 103 * An example of building a custom text field using [decorator]: 104 * 105 * @sample androidx.compose.material3.samples.CustomTextFieldUsingDecorator 106 * @param state [TextFieldState] object that holds the internal editing state of the text field. 107 * @param enabled the enabled state of the text field. When `false`, this decorator will appear 108 * visually disabled. This must be the same value that is passed to [BasicTextField]. 109 * @param lineLimits whether the text field is [SingleLine] or [MultiLine]. This must be the 110 * same value that is passed to [BasicTextField]. 111 * @param outputTransformation [OutputTransformation] that transforms how the contents of the 112 * text field are presented. This must be the same value that is passed to [BasicTextField]. 113 * @param interactionSource the read-only [InteractionSource] representing the stream of 114 * [Interaction]s for this text field. You must first create and pass in your own `remember`ed 115 * [MutableInteractionSource] instance to the [BasicTextField] for it to dispatch events. And 116 * then pass the same instance to this decorator to observe [Interaction]s and customize the 117 * appearance/behavior of the text field in different states. 118 * @param labelPosition the position of the label. See [TextFieldLabelPosition]. 119 * @param label the optional label to be displayed with this text field. The default text style 120 * uses [Typography.bodySmall] when minimized and [Typography.bodyLarge] when expanded. 121 * @param placeholder the optional placeholder to be displayed when the input text is empty. The 122 * default text style uses [Typography.bodyLarge]. 123 * @param leadingIcon the optional leading icon to be displayed at the beginning of the text 124 * field container. 125 * @param trailingIcon the optional trailing icon to be displayed at the end of the text field 126 * container. 127 * @param prefix the optional prefix to be displayed before the input text in the text field. 128 * @param suffix the optional suffix to be displayed after the input text in the text field. 129 * @param supportingText the optional supporting text to be displayed below the text field. 130 * @param isError indicates if the text field's current value is in an error state. When `true`, 131 * this decorator will display its contents in an error color. 132 * @param colors [TextFieldColors] that will be used to resolve the colors used for this text 133 * field decorator in different states. See [TextFieldDefaults.colors]. 134 * @param contentPadding the padding between the input field and the surrounding elements of the 135 * decorator. Note that the padding values may not be respected if they are incompatible with 136 * the text field's size constraints or layout. See 137 * [TextFieldDefaults.contentPaddingWithLabel] and 138 * [TextFieldDefaults.contentPaddingWithoutLabel]. 139 * @param container the container to be drawn behind the text field. By default, this uses 140 * [Container]. Default colors for the container come from the [colors]. 141 */ 142 @Composable 143 fun decorator( 144 state: TextFieldState, 145 enabled: Boolean, 146 lineLimits: TextFieldLineLimits, 147 outputTransformation: OutputTransformation?, 148 interactionSource: InteractionSource, 149 labelPosition: TextFieldLabelPosition = TextFieldLabelPosition.Attached(), 150 label: @Composable (TextFieldLabelScope.() -> Unit)? = null, 151 placeholder: @Composable (() -> Unit)? = null, 152 leadingIcon: @Composable (() -> Unit)? = null, 153 trailingIcon: @Composable (() -> Unit)? = null, 154 prefix: @Composable (() -> Unit)? = null, 155 suffix: @Composable (() -> Unit)? = null, 156 supportingText: @Composable (() -> Unit)? = null, 157 isError: Boolean = false, 158 colors: TextFieldColors = colors(), 159 contentPadding: PaddingValues = 160 if (label == null || labelPosition is TextFieldLabelPosition.Above) { 161 contentPaddingWithoutLabel() 162 } else { 163 contentPaddingWithLabel() 164 }, 165 container: @Composable () -> Unit = { 166 Container( 167 enabled = enabled, 168 isError = isError, 169 interactionSource = interactionSource, 170 colors = colors, 171 shape = shape, 172 focusedIndicatorLineThickness = FocusedIndicatorThickness, 173 unfocusedIndicatorLineThickness = UnfocusedIndicatorThickness, 174 ) 175 } 176 ): TextFieldDecorator = TextFieldDecorator { innerTextField -> 177 val visualText = 178 if (outputTransformation == null) state.text 179 else { 180 // TODO: use constructor to create TextFieldBuffer from TextFieldState when 181 // available 182 lateinit var buffer: TextFieldBuffer 183 state.edit { buffer = this } 184 // after edit completes, mutations on buffer are ineffective 185 with(outputTransformation) { buffer.transformOutput() } 186 buffer.asCharSequence() 187 } 188 189 CommonDecorationBox( 190 type = TextFieldType.Filled, 191 visualText = visualText, 192 innerTextField = innerTextField, 193 placeholder = placeholder, 194 labelPosition = labelPosition, 195 label = label, 196 leadingIcon = leadingIcon, 197 trailingIcon = trailingIcon, 198 prefix = prefix, 199 suffix = suffix, 200 supportingText = supportingText, 201 singleLine = lineLimits == SingleLine, 202 enabled = enabled, 203 isError = isError, 204 interactionSource = interactionSource, 205 colors = colors, 206 contentPadding = contentPadding, 207 container = container, 208 ) 209 } 210 211 /** 212 * Composable that draws a default container for a [TextField] with an indicator line at the 213 * bottom. You can apply it to a [BasicTextField] using [decorator] or [DecorationBox] to create 214 * a custom text field based on the styling of a Material filled text field. The [TextField] 215 * component applies it automatically. 216 * 217 * @param enabled whether the text field is enabled 218 * @param isError whether the text field's current value is in error 219 * @param interactionSource the [InteractionSource] of the text field. Used to determine if the 220 * text field is in focus or not 221 * @param modifier the [Modifier] of this container 222 * @param colors [TextFieldColors] used to resolve colors of the text field 223 * @param shape the shape of this container 224 * @param focusedIndicatorLineThickness thickness of the indicator line when the text field is 225 * focused 226 * @param unfocusedIndicatorLineThickness thickness of the indicator line when the text field is 227 * not focused 228 */ 229 @Composable 230 fun Container( 231 enabled: Boolean, 232 isError: Boolean, 233 interactionSource: InteractionSource, 234 modifier: Modifier = Modifier, 235 colors: TextFieldColors = colors(), 236 shape: Shape = TextFieldDefaults.shape, 237 focusedIndicatorLineThickness: Dp = FocusedIndicatorThickness, 238 unfocusedIndicatorLineThickness: Dp = UnfocusedIndicatorThickness, 239 ) { 240 val focused = interactionSource.collectIsFocusedAsState().value 241 // TODO Load the motionScheme tokens from the component tokens file 242 val containerColor = 243 animateColorAsState( 244 targetValue = colors.containerColor(enabled, isError, focused), 245 animationSpec = MotionSchemeKeyTokens.FastEffects.value(), 246 ) 247 Box( 248 modifier 249 .textFieldBackground(containerColor::value, shape) 250 .indicatorLine( 251 enabled = enabled, 252 isError = isError, 253 interactionSource = interactionSource, 254 colors = colors, 255 textFieldShape = shape, 256 focusedIndicatorLineThickness = focusedIndicatorLineThickness, 257 unfocusedIndicatorLineThickness = unfocusedIndicatorLineThickness, 258 ) 259 ) 260 } 261 262 /** 263 * A modifier to draw a default bottom indicator line for [TextField]. You can apply it to a 264 * [BasicTextField] to create a custom text field based on the styling of a Material filled text 265 * field. 266 * 267 * Consider using [Container], which automatically applies this modifier as well as other text 268 * field container styling. 269 * 270 * @param enabled whether the text field is enabled 271 * @param isError whether the text field's current value is in error 272 * @param interactionSource the [InteractionSource] of the text field. Used to determine if the 273 * text field is in focus or not 274 * @param colors [TextFieldColors] used to resolve colors of the text field. If `null`, defaults 275 * to [TextFieldDefaults.colors]. 276 * @param textFieldShape the shape of the text field container. Used for clipping the indicator. 277 * If `null`, defaults to [TextFieldDefaults.shape]. 278 * @param focusedIndicatorLineThickness thickness of the indicator line when the text field is 279 * focused 280 * @param unfocusedIndicatorLineThickness thickness of the indicator line when the text field is 281 * not focused 282 */ 283 fun Modifier.indicatorLine( 284 enabled: Boolean, 285 isError: Boolean, 286 interactionSource: InteractionSource, 287 colors: TextFieldColors? = null, 288 textFieldShape: Shape? = null, 289 focusedIndicatorLineThickness: Dp = FocusedIndicatorThickness, 290 unfocusedIndicatorLineThickness: Dp = UnfocusedIndicatorThickness 291 ) = 292 this then 293 IndicatorLineElement( 294 enabled = enabled, 295 isError = isError, 296 interactionSource = interactionSource, 297 colors = colors, 298 textFieldShape = textFieldShape, 299 focusedIndicatorLineThickness = focusedIndicatorLineThickness, 300 unfocusedIndicatorLineThickness = unfocusedIndicatorLineThickness, 301 ) 302 303 /** 304 * A decoration box used to create custom text fields based on 305 * [Material Design filled text field](https://m3.material.io/components/text-fields/overview). 306 * 307 * If your text field requires customising elements that aren't exposed by [TextField], consider 308 * using this decoration box to achieve the desired design. 309 * 310 * For example, if you wish to customise the bottom indicator line, you can pass a custom 311 * [Container] to this decoration box's [container]. 312 * 313 * This decoration box is meant to be used in conjunction with overloads of [BasicTextField] 314 * that accept a `decorationBox` parameter. For other overloads of [BasicTextField] that use a 315 * [TextFieldDecorator], see [decorator]. 316 * 317 * An example of building a custom text field using [DecorationBox]: 318 * 319 * @sample androidx.compose.material3.samples.CustomTextFieldBasedOnDecorationBox 320 * @param value the input [String] shown by the text field 321 * @param innerTextField input text field that this decoration box wraps. Pass the 322 * framework-controlled composable parameter `innerTextField` from the `decorationBox` lambda 323 * of the [BasicTextField] 324 * @param enabled the enabled state of the text field. When `false`, this decoration box will 325 * appear visually disabled. This must be the same value that is passed to [BasicTextField]. 326 * @param singleLine indicates if this is a single line or multi line text field. This must be 327 * the same value that is passed to [BasicTextField]. 328 * @param visualTransformation transforms the visual representation of the input [value]. This 329 * must be the same value that is passed to [BasicTextField]. 330 * @param interactionSource the read-only [InteractionSource] representing the stream of 331 * [Interaction]s for this text field. You must first create and pass in your own `remember`ed 332 * [MutableInteractionSource] instance to the [BasicTextField] for it to dispatch events. And 333 * then pass the same instance to this decoration box to observe [Interaction]s and customize 334 * the appearance / behavior of this text field in different states. 335 * @param isError indicates if the text field's current value is in an error state. When `true`, 336 * this decoration box will display its contents in an error color. 337 * @param label the optional label to be displayed with this text field. The default text style 338 * uses [Typography.bodySmall] when minimized and [Typography.bodyLarge] when expanded. 339 * @param placeholder the optional placeholder to be displayed when the text field is in focus 340 * and the input text is empty. The default text style for internal [Text] is 341 * [Typography.bodyLarge]. 342 * @param leadingIcon the optional leading icon to be displayed at the beginning of the text 343 * field container 344 * @param trailingIcon the optional trailing icon to be displayed at the end of the text field 345 * container 346 * @param prefix the optional prefix to be displayed before the input text in the text field 347 * @param suffix the optional suffix to be displayed after the input text in the text field 348 * @param supportingText the optional supporting text to be displayed below the text field 349 * @param shape defines the shape of this decoration box's container 350 * @param colors [TextFieldColors] that will be used to resolve the colors used for this text 351 * field decoration box in different states. See [TextFieldDefaults.colors]. 352 * @param contentPadding the padding between the input field and the surrounding elements of the 353 * decoration box. Note that the padding values may not be respected if they are incompatible 354 * with the text field's size constraints or layout. See 355 * [TextFieldDefaults.contentPaddingWithLabel] and 356 * [TextFieldDefaults.contentPaddingWithoutLabel]. 357 * @param container the container to be drawn behind the text field. By default, this uses 358 * [Container]. Default colors for the container come from the [colors]. 359 */ 360 @Composable 361 fun DecorationBox( 362 value: String, 363 innerTextField: @Composable () -> Unit, 364 enabled: Boolean, 365 singleLine: Boolean, 366 visualTransformation: VisualTransformation, 367 interactionSource: InteractionSource, 368 isError: Boolean = false, 369 label: @Composable (() -> Unit)? = null, 370 placeholder: @Composable (() -> Unit)? = null, 371 leadingIcon: @Composable (() -> Unit)? = null, 372 trailingIcon: @Composable (() -> Unit)? = null, 373 prefix: @Composable (() -> Unit)? = null, 374 suffix: @Composable (() -> Unit)? = null, 375 supportingText: @Composable (() -> Unit)? = null, 376 shape: Shape = TextFieldDefaults.shape, 377 colors: TextFieldColors = colors(), 378 contentPadding: PaddingValues = 379 if (label == null) { 380 contentPaddingWithoutLabel() 381 } else { 382 contentPaddingWithLabel() 383 }, 384 container: @Composable () -> Unit = { 385 Container( 386 enabled = enabled, 387 isError = isError, 388 interactionSource = interactionSource, 389 modifier = Modifier, 390 colors = colors, 391 shape = shape, 392 focusedIndicatorLineThickness = FocusedIndicatorThickness, 393 unfocusedIndicatorLineThickness = UnfocusedIndicatorThickness, 394 ) 395 } 396 ) { 397 val visualText = 398 remember(value, visualTransformation) { 399 visualTransformation.filter(AnnotatedString(value)) 400 } 401 .text 402 .text 403 404 CommonDecorationBox( 405 type = TextFieldType.Filled, 406 visualText = visualText, 407 innerTextField = innerTextField, 408 placeholder = placeholder, 409 labelPosition = TextFieldLabelPosition.Attached(), 410 label = label?.let { { it.invoke() } }, 411 leadingIcon = leadingIcon, 412 trailingIcon = trailingIcon, 413 prefix = prefix, 414 suffix = suffix, 415 supportingText = supportingText, 416 singleLine = singleLine, 417 enabled = enabled, 418 isError = isError, 419 interactionSource = interactionSource, 420 colors = colors, 421 contentPadding = contentPadding, 422 container = container, 423 ) 424 } 425 426 /** 427 * Default content padding of the input field within the [TextField] when there is an inside 428 * label. Note that the top padding represents the padding above the label in the focused state. 429 * The input field is placed directly beneath the label. 430 * 431 * Horizontal padding represents the distance between the input field and the leading/trailing 432 * icons (if present) or the horizontal edges of the container if there are no icons. 433 */ 434 fun contentPaddingWithLabel( 435 start: Dp = TextFieldPadding, 436 end: Dp = TextFieldPadding, 437 top: Dp = TextFieldWithLabelVerticalPadding, 438 bottom: Dp = TextFieldWithLabelVerticalPadding 439 ): PaddingValues = PaddingValues(start, top, end, bottom) 440 441 /** 442 * Default content padding of the input field within the [TextField] when the label is null or 443 * positioned [TextFieldLabelPosition.Above]. 444 * 445 * Horizontal padding represents the distance between the input field and the leading/trailing 446 * icons (if present) or the horizontal edges of the container if there are no icons. 447 */ 448 fun contentPaddingWithoutLabel( 449 start: Dp = TextFieldPadding, 450 top: Dp = TextFieldPadding, 451 end: Dp = TextFieldPadding, 452 bottom: Dp = TextFieldPadding 453 ): PaddingValues = PaddingValues(start, top, end, bottom) 454 455 /** 456 * Default padding applied to supporting text for both [TextField] and [OutlinedTextField]. See 457 * [PaddingValues] for more details. 458 */ 459 // TODO(246775477): consider making this public 460 internal fun supportingTextPadding( 461 start: Dp = TextFieldPadding, 462 top: Dp = SupportingTopPadding, 463 end: Dp = TextFieldPadding, 464 bottom: Dp = 0.dp, 465 ): PaddingValues = PaddingValues(start, top, end, bottom) 466 467 /** 468 * Creates a [TextFieldColors] that represents the default input text, container, and content 469 * colors (including label, placeholder, icons, etc.) used in a [TextField]. 470 */ 471 @Composable 472 fun colors() = 473 MaterialTheme.colorScheme.defaultTextFieldColors(LocalTextSelectionColors.current) 474 475 /** 476 * Creates a [TextFieldColors] that represents the default input text, container, and content 477 * colors (including label, placeholder, icons, etc.) used in a [TextField]. 478 * 479 * @param focusedTextColor the color used for the input text of this text field when focused 480 * @param unfocusedTextColor the color used for the input text of this text field when not 481 * focused 482 * @param disabledTextColor the color used for the input text of this text field when disabled 483 * @param errorTextColor the color used for the input text of this text field when in error 484 * state 485 * @param focusedContainerColor the container color for this text field when focused 486 * @param unfocusedContainerColor the container color for this text field when not focused 487 * @param disabledContainerColor the container color for this text field when disabled 488 * @param errorContainerColor the container color for this text field when in error state 489 * @param cursorColor the cursor color for this text field 490 * @param errorCursorColor the cursor color for this text field when in error state 491 * @param selectionColors the colors used when the input text of this text field is selected 492 * @param focusedIndicatorColor the indicator color for this text field when focused 493 * @param unfocusedIndicatorColor the indicator color for this text field when not focused 494 * @param disabledIndicatorColor the indicator color for this text field when disabled 495 * @param errorIndicatorColor the indicator color for this text field when in error state 496 * @param focusedLeadingIconColor the leading icon color for this text field when focused 497 * @param unfocusedLeadingIconColor the leading icon color for this text field when not focused 498 * @param disabledLeadingIconColor the leading icon color for this text field when disabled 499 * @param errorLeadingIconColor the leading icon color for this text field when in error state 500 * @param focusedTrailingIconColor the trailing icon color for this text field when focused 501 * @param unfocusedTrailingIconColor the trailing icon color for this text field when not 502 * focused 503 * @param disabledTrailingIconColor the trailing icon color for this text field when disabled 504 * @param errorTrailingIconColor the trailing icon color for this text field when in error state 505 * @param focusedLabelColor the label color for this text field when focused 506 * @param unfocusedLabelColor the label color for this text field when not focused 507 * @param disabledLabelColor the label color for this text field when disabled 508 * @param errorLabelColor the label color for this text field when in error state 509 * @param focusedPlaceholderColor the placeholder color for this text field when focused 510 * @param unfocusedPlaceholderColor the placeholder color for this text field when not focused 511 * @param disabledPlaceholderColor the placeholder color for this text field when disabled 512 * @param errorPlaceholderColor the placeholder color for this text field when in error state 513 * @param focusedSupportingTextColor the supporting text color for this text field when focused 514 * @param unfocusedSupportingTextColor the supporting text color for this text field when not 515 * focused 516 * @param disabledSupportingTextColor the supporting text color for this text field when 517 * disabled 518 * @param errorSupportingTextColor the supporting text color for this text field when in error 519 * state 520 * @param focusedPrefixColor the prefix color for this text field when focused 521 * @param unfocusedPrefixColor the prefix color for this text field when not focused 522 * @param disabledPrefixColor the prefix color for this text field when disabled 523 * @param errorPrefixColor the prefix color for this text field when in error state 524 * @param focusedSuffixColor the suffix color for this text field when focused 525 * @param unfocusedSuffixColor the suffix color for this text field when not focused 526 * @param disabledSuffixColor the suffix color for this text field when disabled 527 * @param errorSuffixColor the suffix color for this text field when in error state 528 */ 529 @Composable 530 fun colors( 531 focusedTextColor: Color = Color.Unspecified, 532 unfocusedTextColor: Color = Color.Unspecified, 533 disabledTextColor: Color = Color.Unspecified, 534 errorTextColor: Color = Color.Unspecified, 535 focusedContainerColor: Color = Color.Unspecified, 536 unfocusedContainerColor: Color = Color.Unspecified, 537 disabledContainerColor: Color = Color.Unspecified, 538 errorContainerColor: Color = Color.Unspecified, 539 cursorColor: Color = Color.Unspecified, 540 errorCursorColor: Color = Color.Unspecified, 541 selectionColors: TextSelectionColors? = null, 542 focusedIndicatorColor: Color = Color.Unspecified, 543 unfocusedIndicatorColor: Color = Color.Unspecified, 544 disabledIndicatorColor: Color = Color.Unspecified, 545 errorIndicatorColor: Color = Color.Unspecified, 546 focusedLeadingIconColor: Color = Color.Unspecified, 547 unfocusedLeadingIconColor: Color = Color.Unspecified, 548 disabledLeadingIconColor: Color = Color.Unspecified, 549 errorLeadingIconColor: Color = Color.Unspecified, 550 focusedTrailingIconColor: Color = Color.Unspecified, 551 unfocusedTrailingIconColor: Color = Color.Unspecified, 552 disabledTrailingIconColor: Color = Color.Unspecified, 553 errorTrailingIconColor: Color = Color.Unspecified, 554 focusedLabelColor: Color = Color.Unspecified, 555 unfocusedLabelColor: Color = Color.Unspecified, 556 disabledLabelColor: Color = Color.Unspecified, 557 errorLabelColor: Color = Color.Unspecified, 558 focusedPlaceholderColor: Color = Color.Unspecified, 559 unfocusedPlaceholderColor: Color = Color.Unspecified, 560 disabledPlaceholderColor: Color = Color.Unspecified, 561 errorPlaceholderColor: Color = Color.Unspecified, 562 focusedSupportingTextColor: Color = Color.Unspecified, 563 unfocusedSupportingTextColor: Color = Color.Unspecified, 564 disabledSupportingTextColor: Color = Color.Unspecified, 565 errorSupportingTextColor: Color = Color.Unspecified, 566 focusedPrefixColor: Color = Color.Unspecified, 567 unfocusedPrefixColor: Color = Color.Unspecified, 568 disabledPrefixColor: Color = Color.Unspecified, 569 errorPrefixColor: Color = Color.Unspecified, 570 focusedSuffixColor: Color = Color.Unspecified, 571 unfocusedSuffixColor: Color = Color.Unspecified, 572 disabledSuffixColor: Color = Color.Unspecified, 573 errorSuffixColor: Color = Color.Unspecified, 574 ): TextFieldColors = 575 MaterialTheme.colorScheme 576 .defaultTextFieldColors(LocalTextSelectionColors.current) 577 .copy( 578 focusedTextColor = focusedTextColor, 579 unfocusedTextColor = unfocusedTextColor, 580 disabledTextColor = disabledTextColor, 581 errorTextColor = errorTextColor, 582 focusedContainerColor = focusedContainerColor, 583 unfocusedContainerColor = unfocusedContainerColor, 584 disabledContainerColor = disabledContainerColor, 585 errorContainerColor = errorContainerColor, 586 cursorColor = cursorColor, 587 errorCursorColor = errorCursorColor, 588 textSelectionColors = selectionColors, 589 focusedIndicatorColor = focusedIndicatorColor, 590 unfocusedIndicatorColor = unfocusedIndicatorColor, 591 disabledIndicatorColor = disabledIndicatorColor, 592 errorIndicatorColor = errorIndicatorColor, 593 focusedLeadingIconColor = focusedLeadingIconColor, 594 unfocusedLeadingIconColor = unfocusedLeadingIconColor, 595 disabledLeadingIconColor = disabledLeadingIconColor, 596 errorLeadingIconColor = errorLeadingIconColor, 597 focusedTrailingIconColor = focusedTrailingIconColor, 598 unfocusedTrailingIconColor = unfocusedTrailingIconColor, 599 disabledTrailingIconColor = disabledTrailingIconColor, 600 errorTrailingIconColor = errorTrailingIconColor, 601 focusedLabelColor = focusedLabelColor, 602 unfocusedLabelColor = unfocusedLabelColor, 603 disabledLabelColor = disabledLabelColor, 604 errorLabelColor = errorLabelColor, 605 focusedPlaceholderColor = focusedPlaceholderColor, 606 unfocusedPlaceholderColor = unfocusedPlaceholderColor, 607 disabledPlaceholderColor = disabledPlaceholderColor, 608 errorPlaceholderColor = errorPlaceholderColor, 609 focusedSupportingTextColor = focusedSupportingTextColor, 610 unfocusedSupportingTextColor = unfocusedSupportingTextColor, 611 disabledSupportingTextColor = disabledSupportingTextColor, 612 errorSupportingTextColor = errorSupportingTextColor, 613 focusedPrefixColor = focusedPrefixColor, 614 unfocusedPrefixColor = unfocusedPrefixColor, 615 disabledPrefixColor = disabledPrefixColor, 616 errorPrefixColor = errorPrefixColor, 617 focusedSuffixColor = focusedSuffixColor, 618 unfocusedSuffixColor = unfocusedSuffixColor, 619 disabledSuffixColor = disabledSuffixColor, 620 errorSuffixColor = errorSuffixColor, 621 ) 622 623 internal fun ColorScheme.defaultTextFieldColors( 624 localTextSelectionColors: TextSelectionColors 625 ): TextFieldColors { 626 return defaultTextFieldColorsCached?.let { cachedColors -> 627 if (cachedColors.textSelectionColors == localTextSelectionColors) { 628 cachedColors 629 } else { 630 cachedColors.copy(textSelectionColors = localTextSelectionColors).also { 631 defaultTextFieldColorsCached = it 632 } 633 } 634 } 635 ?: TextFieldColors( 636 focusedTextColor = fromToken(FilledTextFieldTokens.FocusInputColor), 637 unfocusedTextColor = fromToken(FilledTextFieldTokens.InputColor), 638 disabledTextColor = 639 fromToken(FilledTextFieldTokens.DisabledInputColor) 640 .copy(alpha = FilledTextFieldTokens.DisabledInputOpacity), 641 errorTextColor = fromToken(FilledTextFieldTokens.ErrorInputColor), 642 focusedContainerColor = fromToken(FilledTextFieldTokens.ContainerColor), 643 unfocusedContainerColor = fromToken(FilledTextFieldTokens.ContainerColor), 644 disabledContainerColor = fromToken(FilledTextFieldTokens.ContainerColor), 645 errorContainerColor = fromToken(FilledTextFieldTokens.ContainerColor), 646 cursorColor = fromToken(FilledTextFieldTokens.CaretColor), 647 errorCursorColor = fromToken(FilledTextFieldTokens.ErrorFocusCaretColor), 648 textSelectionColors = localTextSelectionColors, 649 focusedIndicatorColor = 650 fromToken(FilledTextFieldTokens.FocusActiveIndicatorColor), 651 unfocusedIndicatorColor = fromToken(FilledTextFieldTokens.ActiveIndicatorColor), 652 disabledIndicatorColor = 653 fromToken(FilledTextFieldTokens.DisabledActiveIndicatorColor) 654 .copy(alpha = FilledTextFieldTokens.DisabledActiveIndicatorOpacity), 655 errorIndicatorColor = 656 fromToken(FilledTextFieldTokens.ErrorActiveIndicatorColor), 657 focusedLeadingIconColor = 658 fromToken(FilledTextFieldTokens.FocusLeadingIconColor), 659 unfocusedLeadingIconColor = fromToken(FilledTextFieldTokens.LeadingIconColor), 660 disabledLeadingIconColor = 661 fromToken(FilledTextFieldTokens.DisabledLeadingIconColor) 662 .copy(alpha = FilledTextFieldTokens.DisabledLeadingIconOpacity), 663 errorLeadingIconColor = fromToken(FilledTextFieldTokens.ErrorLeadingIconColor), 664 focusedTrailingIconColor = 665 fromToken(FilledTextFieldTokens.FocusTrailingIconColor), 666 unfocusedTrailingIconColor = fromToken(FilledTextFieldTokens.TrailingIconColor), 667 disabledTrailingIconColor = 668 fromToken(FilledTextFieldTokens.DisabledTrailingIconColor) 669 .copy(alpha = FilledTextFieldTokens.DisabledTrailingIconOpacity), 670 errorTrailingIconColor = 671 fromToken(FilledTextFieldTokens.ErrorTrailingIconColor), 672 focusedLabelColor = fromToken(FilledTextFieldTokens.FocusLabelColor), 673 unfocusedLabelColor = fromToken(FilledTextFieldTokens.LabelColor), 674 disabledLabelColor = 675 fromToken(FilledTextFieldTokens.DisabledLabelColor) 676 .copy(alpha = FilledTextFieldTokens.DisabledLabelOpacity), 677 errorLabelColor = fromToken(FilledTextFieldTokens.ErrorLabelColor), 678 focusedPlaceholderColor = 679 fromToken(FilledTextFieldTokens.InputPlaceholderColor), 680 unfocusedPlaceholderColor = 681 fromToken(FilledTextFieldTokens.InputPlaceholderColor), 682 disabledPlaceholderColor = 683 fromToken(FilledTextFieldTokens.DisabledInputColor) 684 .copy(alpha = FilledTextFieldTokens.DisabledInputOpacity), 685 errorPlaceholderColor = fromToken(FilledTextFieldTokens.InputPlaceholderColor), 686 focusedSupportingTextColor = 687 fromToken(FilledTextFieldTokens.FocusSupportingColor), 688 unfocusedSupportingTextColor = fromToken(FilledTextFieldTokens.SupportingColor), 689 disabledSupportingTextColor = 690 fromToken(FilledTextFieldTokens.DisabledSupportingColor) 691 .copy(alpha = FilledTextFieldTokens.DisabledSupportingOpacity), 692 errorSupportingTextColor = 693 fromToken(FilledTextFieldTokens.ErrorSupportingColor), 694 focusedPrefixColor = fromToken(FilledTextFieldTokens.InputPrefixColor), 695 unfocusedPrefixColor = fromToken(FilledTextFieldTokens.InputPrefixColor), 696 disabledPrefixColor = 697 fromToken(FilledTextFieldTokens.InputPrefixColor) 698 .copy(alpha = FilledTextFieldTokens.DisabledInputOpacity), 699 errorPrefixColor = fromToken(FilledTextFieldTokens.InputPrefixColor), 700 focusedSuffixColor = fromToken(FilledTextFieldTokens.InputSuffixColor), 701 unfocusedSuffixColor = fromToken(FilledTextFieldTokens.InputSuffixColor), 702 disabledSuffixColor = 703 fromToken(FilledTextFieldTokens.InputSuffixColor) 704 .copy(alpha = FilledTextFieldTokens.DisabledInputOpacity), 705 errorSuffixColor = fromToken(FilledTextFieldTokens.InputSuffixColor), 706 ) 707 .also { defaultTextFieldColorsCached = it } 708 } 709 710 @Deprecated( 711 level = DeprecationLevel.HIDDEN, 712 message = "Maintained for binary compatibility. Use overload with `textFieldShape`.", 713 ) 714 @ExperimentalMaterial3Api 715 fun Modifier.indicatorLine( 716 enabled: Boolean, 717 isError: Boolean, 718 interactionSource: InteractionSource, 719 colors: TextFieldColors, 720 focusedIndicatorLineThickness: Dp = FocusedIndicatorThickness, 721 unfocusedIndicatorLineThickness: Dp = UnfocusedIndicatorThickness 722 ) = 723 indicatorLine( 724 enabled = enabled, 725 isError = isError, 726 interactionSource = interactionSource, 727 colors = colors, 728 textFieldShape = null, 729 focusedIndicatorLineThickness = focusedIndicatorLineThickness, 730 unfocusedIndicatorLineThickness = unfocusedIndicatorLineThickness, 731 ) 732 733 @Deprecated( 734 message = "Renamed to TextFieldDefaults.Container", 735 replaceWith = 736 ReplaceWith( 737 "Container(\n" + 738 " enabled = enabled,\n" + 739 " isError = isError,\n" + 740 " interactionSource = interactionSource,\n" + 741 " colors = colors,\n" + 742 " shape = shape,\n" + 743 ")" 744 ), 745 level = DeprecationLevel.WARNING 746 ) 747 @ExperimentalMaterial3Api 748 @Composable 749 fun ContainerBox( 750 enabled: Boolean, 751 isError: Boolean, 752 interactionSource: InteractionSource, 753 colors: TextFieldColors, 754 shape: Shape = TextFieldDefaults.shape, 755 ) = 756 Container( 757 enabled = enabled, 758 isError = isError, 759 interactionSource = interactionSource, 760 modifier = Modifier, 761 colors = colors, 762 shape = shape, 763 focusedIndicatorLineThickness = FocusedIndicatorThickness, 764 unfocusedIndicatorLineThickness = UnfocusedIndicatorThickness, 765 ) 766 767 @Deprecated( 768 message = "Renamed to `OutlinedTextFieldDefaults.shape`", 769 replaceWith = 770 ReplaceWith( 771 "OutlinedTextFieldDefaults.shape", 772 "androidx.compose.material.OutlinedTextFieldDefaults" 773 ), 774 level = DeprecationLevel.WARNING 775 ) 776 val outlinedShape: Shape 777 @Composable get() = OutlinedTextFieldDefaults.shape 778 779 @Deprecated( 780 message = "Renamed to `TextFieldDefaults.shape`", 781 replaceWith = ReplaceWith("TextFieldDefaults.shape"), 782 level = DeprecationLevel.WARNING 783 ) 784 val filledShape: Shape 785 @Composable get() = shape 786 787 @Deprecated( 788 message = 789 "Split into `TextFieldDefaults.UnfocusedIndicatorThickness` and " + 790 "`OutlinedTextFieldDefaults.UnfocusedBorderThickness`. Please update as appropriate.", 791 replaceWith = ReplaceWith("TextFieldDefaults.UnfocusedIndicatorThickness"), 792 level = DeprecationLevel.WARNING, 793 ) 794 val UnfocusedBorderThickness = UnfocusedIndicatorThickness 795 796 @Deprecated( 797 message = 798 "Split into `TextFieldDefaults.FocusedIndicatorThickness` and " + 799 "`OutlinedTextFieldDefaults.FocusedBorderThickness`. Please update as appropriate.", 800 replaceWith = ReplaceWith("TextFieldDefaults.FocusedIndicatorThickness"), 801 level = DeprecationLevel.WARNING, 802 ) 803 val FocusedBorderThickness = FocusedIndicatorThickness 804 805 @Deprecated( 806 message = "Renamed to `TextFieldDefaults.contentPaddingWithLabel`", 807 replaceWith = 808 ReplaceWith( 809 "TextFieldDefaults.contentPaddingWithLabel(\n" + 810 " start = start,\n" + 811 " top = top,\n" + 812 " end = end,\n" + 813 " bottom = bottom,\n" + 814 " )" 815 ), 816 level = DeprecationLevel.WARNING 817 ) 818 fun textFieldWithLabelPadding( 819 start: Dp = TextFieldPadding, 820 end: Dp = TextFieldPadding, 821 top: Dp = TextFieldWithLabelVerticalPadding, 822 bottom: Dp = TextFieldWithLabelVerticalPadding 823 ): PaddingValues = 824 contentPaddingWithLabel( 825 start = start, 826 top = top, 827 end = end, 828 bottom = bottom, 829 ) 830 831 @Deprecated( 832 message = "Renamed to `TextFieldDefaults.contentPaddingWithoutLabel`", 833 replaceWith = 834 ReplaceWith( 835 "TextFieldDefaults.contentPaddingWithoutLabel(\n" + 836 " start = start,\n" + 837 " top = top,\n" + 838 " end = end,\n" + 839 " bottom = bottom,\n" + 840 " )" 841 ), 842 level = DeprecationLevel.WARNING 843 ) 844 fun textFieldWithoutLabelPadding( 845 start: Dp = TextFieldPadding, 846 top: Dp = TextFieldPadding, 847 end: Dp = TextFieldPadding, 848 bottom: Dp = TextFieldPadding 849 ): PaddingValues = 850 contentPaddingWithoutLabel( 851 start = start, 852 top = top, 853 end = end, 854 bottom = bottom, 855 ) 856 857 @Deprecated( 858 message = "Renamed to `OutlinedTextFieldDefaults.contentPadding`", 859 replaceWith = 860 ReplaceWith( 861 "OutlinedTextFieldDefaults.contentPadding(\n" + 862 " start = start,\n" + 863 " top = top,\n" + 864 " end = end,\n" + 865 " bottom = bottom,\n" + 866 " )", 867 "androidx.compose.material.OutlinedTextFieldDefaults" 868 ), 869 level = DeprecationLevel.WARNING 870 ) 871 fun outlinedTextFieldPadding( 872 start: Dp = TextFieldPadding, 873 top: Dp = TextFieldPadding, 874 end: Dp = TextFieldPadding, 875 bottom: Dp = TextFieldPadding 876 ): PaddingValues = 877 OutlinedTextFieldDefaults.contentPadding( 878 start = start, 879 top = top, 880 end = end, 881 bottom = bottom, 882 ) 883 } 884 885 /** 886 * Contains the default values used by [OutlinedTextField]. For defaults used in [TextField], see 887 * [TextFieldDefaults]. 888 */ 889 @Immutable 890 object OutlinedTextFieldDefaults { 891 /** Default shape for an [OutlinedTextField]. */ 892 val shape: Shape 893 @Composable get() = OutlinedTextFieldTokens.ContainerShape.value 894 895 /** 896 * The default min height applied to an [OutlinedTextField]. Note that you can override it by 897 * applying Modifier.heightIn directly on a text field. 898 */ 899 val MinHeight = 56.dp 900 901 /** 902 * The default min width applied to an [OutlinedTextField]. Note that you can override it by 903 * applying Modifier.widthIn directly on a text field. 904 */ 905 val MinWidth = 280.dp 906 907 /** The default thickness of the border in [OutlinedTextField] in unfocused state. */ 908 val UnfocusedBorderThickness = 1.dp 909 910 /** The default thickness of the border in [OutlinedTextField] in focused state. */ 911 val FocusedBorderThickness = 2.dp 912 913 /** 914 * A decorator used to create custom text fields based on 915 * [Material Design outlined text field](https://m3.material.io/components/text-fields/overview). 916 * 917 * If your text field requires customising elements that aren't exposed by [OutlinedTextField], 918 * such as the border thickness, consider using this decorator to achieve the desired design. 919 * 920 * For example, if you wish to customize the thickness of the border, you can pass a custom 921 * [Container] to this decoration box's [container]. 922 * 923 * This decorator is meant to be used in conjunction with the overload of [BasicTextField] that 924 * accepts a [TextFieldDecorator] parameter. For other overloads of [BasicTextField] that use a 925 * `decorationBox`, see [DecorationBox]. 926 * 927 * An example of building a custom text field using [decorator]: 928 * 929 * @sample androidx.compose.material3.samples.CustomOutlinedTextFieldUsingDecorator 930 * @param state [TextFieldState] object that holds the internal editing state of the text field. 931 * @param enabled the enabled state of the text field. When `false`, this decorator will appear 932 * visually disabled. This must be the same value that is passed to [BasicTextField]. 933 * @param lineLimits whether the text field is [SingleLine] or [MultiLine]. This must be the 934 * same value that is passed to [BasicTextField]. 935 * @param outputTransformation [OutputTransformation] that transforms how the contents of the 936 * text field are presented. This must be the same value that is passed to [BasicTextField]. 937 * @param interactionSource the read-only [InteractionSource] representing the stream of 938 * [Interaction]s for this text field. You must first create and pass in your own `remember`ed 939 * [MutableInteractionSource] instance to the [BasicTextField] for it to dispatch events. And 940 * then pass the same instance to this decorator to observe [Interaction]s and customize the 941 * appearance/behavior of the text field in different states. 942 * @param labelPosition the position of the label. See [TextFieldLabelPosition]. 943 * @param label the optional label to be displayed with this text field. The default text style 944 * uses [Typography.bodySmall] when minimized and [Typography.bodyLarge] when expanded. 945 * @param placeholder the optional placeholder to be displayed when the input text is empty. The 946 * default text style uses [Typography.bodyLarge]. 947 * @param leadingIcon the optional leading icon to be displayed at the beginning of the text 948 * field container. 949 * @param trailingIcon the optional trailing icon to be displayed at the end of the text field 950 * container. 951 * @param prefix the optional prefix to be displayed before the input text in the text field. 952 * @param suffix the optional suffix to be displayed after the input text in the text field. 953 * @param supportingText the optional supporting text to be displayed below the text field. 954 * @param isError indicates if the text field's current value is in an error state. When `true`, 955 * this decorator will display its contents in an error color. 956 * @param colors [TextFieldColors] that will be used to resolve the colors used for this text 957 * field decorator in different states. See [OutlinedTextFieldDefaults.colors]. 958 * @param contentPadding the padding between the input field and the surrounding elements of the 959 * decorator. Note that the padding values may not be respected if they are incompatible with 960 * the text field's size constraints or layout. See 961 * [OutlinedTextFieldDefaults.contentPadding]. 962 * @param container the container to be drawn behind the text field. By default, this is 963 * transparent and only includes a border. The cutout in the border to fit the [label] will be 964 * automatically added by the framework. Default colors for the container come from the 965 * [colors]. 966 */ 967 @Composable decoratornull968 fun decorator( 969 state: TextFieldState, 970 enabled: Boolean, 971 lineLimits: TextFieldLineLimits, 972 outputTransformation: OutputTransformation?, 973 interactionSource: InteractionSource, 974 labelPosition: TextFieldLabelPosition = TextFieldLabelPosition.Attached(), 975 label: @Composable (TextFieldLabelScope.() -> Unit)? = null, 976 placeholder: @Composable (() -> Unit)? = null, 977 leadingIcon: @Composable (() -> Unit)? = null, 978 trailingIcon: @Composable (() -> Unit)? = null, 979 prefix: @Composable (() -> Unit)? = null, 980 suffix: @Composable (() -> Unit)? = null, 981 supportingText: @Composable (() -> Unit)? = null, 982 isError: Boolean = false, 983 colors: TextFieldColors = colors(), 984 contentPadding: PaddingValues = contentPadding(), 985 container: @Composable () -> Unit = { 986 Container( 987 enabled = enabled, 988 isError = isError, 989 interactionSource = interactionSource, 990 colors = colors, 991 shape = shape, 992 focusedBorderThickness = FocusedBorderThickness, 993 unfocusedBorderThickness = UnfocusedBorderThickness, 994 ) 995 } 996 ): TextFieldDecorator = TextFieldDecorator { innerTextField -> 997 val visualText = 998 if (outputTransformation == null) state.text 999 else { 1000 // TODO: use constructor to create TextFieldBuffer from TextFieldState when 1001 // available 1002 lateinit var buffer: TextFieldBuffer <lambda>null1003 state.edit { buffer = this } 1004 // after edit completes, mutations on buffer are ineffective <lambda>null1005 with(outputTransformation) { buffer.transformOutput() } 1006 buffer.asCharSequence() 1007 } 1008 1009 CommonDecorationBox( 1010 type = TextFieldType.Outlined, 1011 visualText = visualText, 1012 innerTextField = innerTextField, 1013 placeholder = placeholder, 1014 labelPosition = labelPosition, 1015 label = label, 1016 leadingIcon = leadingIcon, 1017 trailingIcon = trailingIcon, 1018 prefix = prefix, 1019 suffix = suffix, 1020 supportingText = supportingText, 1021 singleLine = lineLimits == SingleLine, 1022 enabled = enabled, 1023 isError = isError, 1024 interactionSource = interactionSource, 1025 colors = colors, 1026 contentPadding = contentPadding, 1027 container = container, 1028 ) 1029 } 1030 1031 /** 1032 * Composable that draws a default container for an [OutlinedTextField] with a border stroke. 1033 * You can apply it to a [BasicTextField] using [decorator] or [DecorationBox] to create a 1034 * custom text field based on the styling of a Material outlined text field. The 1035 * [OutlinedTextField] component applies it automatically. 1036 * 1037 * @param enabled whether the text field is enabled 1038 * @param isError whether the text field's current value is in error 1039 * @param interactionSource the [InteractionSource] of the text field. Used to determine if the 1040 * text field is in focus or not 1041 * @param modifier the [Modifier] of this container 1042 * @param colors [TextFieldColors] used to resolve colors of the text field 1043 * @param shape the shape of this container 1044 * @param focusedBorderThickness thickness of the border when the text field is focused 1045 * @param unfocusedBorderThickness thickness of the border when the text field is not focused 1046 */ 1047 @Composable Containernull1048 fun Container( 1049 enabled: Boolean, 1050 isError: Boolean, 1051 interactionSource: InteractionSource, 1052 modifier: Modifier = Modifier, 1053 colors: TextFieldColors = colors(), 1054 shape: Shape = OutlinedTextFieldDefaults.shape, 1055 focusedBorderThickness: Dp = FocusedBorderThickness, 1056 unfocusedBorderThickness: Dp = UnfocusedBorderThickness, 1057 ) { 1058 val focused = interactionSource.collectIsFocusedAsState().value 1059 val borderStroke = 1060 animateBorderStrokeAsState( 1061 enabled, 1062 isError, 1063 focused, 1064 colors, 1065 focusedBorderThickness, 1066 unfocusedBorderThickness, 1067 ) 1068 // TODO Load the motionScheme tokens from the component tokens file 1069 val containerColor = 1070 animateColorAsState( 1071 targetValue = colors.containerColor(enabled, isError, focused), 1072 animationSpec = MotionSchemeKeyTokens.FastEffects.value(), 1073 ) 1074 Box( 1075 modifier 1076 .border(borderStroke.value, shape) 1077 .textFieldBackground(containerColor::value, shape) 1078 ) 1079 } 1080 1081 /** 1082 * A decoration box used to create custom text fields based on 1083 * [Material Design outlined text field](https://m3.material.io/components/text-fields/overview). 1084 * 1085 * If your text field requires customising elements that aren't exposed by [OutlinedTextField], 1086 * consider using this decoration box to achieve the desired design. 1087 * 1088 * For example, if you wish to customize the thickness of the border, you can pass a custom 1089 * [Container] to this decoration box's [container]. 1090 * 1091 * This decoration box is meant to be used in conjunction with overloads of [BasicTextField] 1092 * that accept a `decorationBox` parameter. For other overloads of [BasicTextField] that use a 1093 * [TextFieldDecorator], see [decorator]. 1094 * 1095 * An example of building a custom text field using [DecorationBox]: 1096 * 1097 * @sample androidx.compose.material3.samples.CustomOutlinedTextFieldBasedOnDecorationBox 1098 * @param value the input [String] shown by the text field 1099 * @param innerTextField input text field that this decoration box wraps. Pass the 1100 * framework-controlled composable parameter `innerTextField` from the `decorationBox` lambda 1101 * of the [BasicTextField] 1102 * @param enabled the enabled state of the text field. When `false`, this decoration box will 1103 * appear visually disabled. This must be the same value that is passed to [BasicTextField]. 1104 * @param singleLine indicates if this is a single line or multi line text field. This must be 1105 * the same value that is passed to [BasicTextField]. 1106 * @param visualTransformation transforms the visual representation of the input [value]. This 1107 * must be the same value that is passed to [BasicTextField]. 1108 * @param interactionSource the read-only [InteractionSource] representing the stream of 1109 * [Interaction]s for this text field. You must first create and pass in your own `remember`ed 1110 * [MutableInteractionSource] instance to the [BasicTextField] for it to dispatch events. And 1111 * then pass the same instance to this decoration box to observe [Interaction]s and customize 1112 * the appearance / behavior of this text field in different states. 1113 * @param isError indicates if the text field's current value is in an error state. When `true`, 1114 * this decoration box will display its contents in an error color. 1115 * @param label the optional label to be displayed with this text field. The default text style 1116 * uses [Typography.bodySmall] when minimized and [Typography.bodyLarge] when expanded. 1117 * @param placeholder the optional placeholder to be displayed when the text field is in focus 1118 * and the input text is empty. The default text style for internal [Text] is 1119 * [Typography.bodyLarge]. 1120 * @param leadingIcon the optional leading icon to be displayed at the beginning of the text 1121 * field container 1122 * @param trailingIcon the optional trailing icon to be displayed at the end of the text field 1123 * container 1124 * @param prefix the optional prefix to be displayed before the input text in the text field 1125 * @param suffix the optional suffix to be displayed after the input text in the text field 1126 * @param supportingText the optional supporting text to be displayed below the text field 1127 * @param colors [TextFieldColors] that will be used to resolve the colors used for this text 1128 * field in different states. See [OutlinedTextFieldDefaults.colors]. 1129 * @param contentPadding the padding between the input field and the surrounding elements of the 1130 * decoration box. Note that the padding values may not be respected if they are incompatible 1131 * with the text field's size constraints or layout. See 1132 * [OutlinedTextFieldDefaults.contentPadding]. 1133 * @param container the container to be drawn behind the text field. By default, this is 1134 * transparent and only includes a border. The cutout in the border to fit the [label] will be 1135 * automatically added by the framework. Default colors for the container come from the 1136 * [colors]. 1137 */ 1138 @Composable DecorationBoxnull1139 fun DecorationBox( 1140 value: String, 1141 innerTextField: @Composable () -> Unit, 1142 enabled: Boolean, 1143 singleLine: Boolean, 1144 visualTransformation: VisualTransformation, 1145 interactionSource: InteractionSource, 1146 isError: Boolean = false, 1147 label: @Composable (() -> Unit)? = null, 1148 placeholder: @Composable (() -> Unit)? = null, 1149 leadingIcon: @Composable (() -> Unit)? = null, 1150 trailingIcon: @Composable (() -> Unit)? = null, 1151 prefix: @Composable (() -> Unit)? = null, 1152 suffix: @Composable (() -> Unit)? = null, 1153 supportingText: @Composable (() -> Unit)? = null, 1154 colors: TextFieldColors = colors(), 1155 contentPadding: PaddingValues = contentPadding(), 1156 container: @Composable () -> Unit = { 1157 Container( 1158 enabled = enabled, 1159 isError = isError, 1160 interactionSource = interactionSource, 1161 modifier = Modifier, 1162 colors = colors, 1163 shape = shape, 1164 focusedBorderThickness = FocusedBorderThickness, 1165 unfocusedBorderThickness = UnfocusedBorderThickness, 1166 ) 1167 } 1168 ) { 1169 val visualText = <lambda>null1170 remember(value, visualTransformation) { 1171 visualTransformation.filter(AnnotatedString(value)) 1172 } 1173 .text 1174 .text 1175 1176 CommonDecorationBox( 1177 type = TextFieldType.Outlined, 1178 visualText = visualText, 1179 innerTextField = innerTextField, 1180 placeholder = placeholder, 1181 labelPosition = TextFieldLabelPosition.Attached(), <lambda>null1182 label = label?.let { { it.invoke() } }, 1183 leadingIcon = leadingIcon, 1184 trailingIcon = trailingIcon, 1185 prefix = prefix, 1186 suffix = suffix, 1187 supportingText = supportingText, 1188 singleLine = singleLine, 1189 enabled = enabled, 1190 isError = isError, 1191 interactionSource = interactionSource, 1192 colors = colors, 1193 contentPadding = contentPadding, 1194 container = container, 1195 ) 1196 } 1197 1198 /** 1199 * Default content padding of the input field within the [OutlinedTextField]. 1200 * 1201 * Horizontal padding represents the distance between the input field and the leading/trailing 1202 * icons (if present) or the horizontal edges of the container if there are no icons. 1203 */ contentPaddingnull1204 fun contentPadding( 1205 start: Dp = TextFieldPadding, 1206 top: Dp = TextFieldPadding, 1207 end: Dp = TextFieldPadding, 1208 bottom: Dp = TextFieldPadding 1209 ): PaddingValues = PaddingValues(start, top, end, bottom) 1210 1211 /** 1212 * Creates a [TextFieldColors] that represents the default input text, container, and content 1213 * colors (including label, placeholder, icons, etc.) used in an [OutlinedTextField]. 1214 */ 1215 @Composable fun colors() = MaterialTheme.colorScheme.defaultOutlinedTextFieldColors 1216 1217 /** 1218 * Creates a [TextFieldColors] that represents the default input text, container, and content 1219 * colors (including label, placeholder, icons, etc.) used in an [OutlinedTextField]. 1220 * 1221 * @param focusedTextColor the color used for the input text of this text field when focused 1222 * @param unfocusedTextColor the color used for the input text of this text field when not 1223 * focused 1224 * @param disabledTextColor the color used for the input text of this text field when disabled 1225 * @param errorTextColor the color used for the input text of this text field when in error 1226 * state 1227 * @param focusedContainerColor the container color for this text field when focused 1228 * @param unfocusedContainerColor the container color for this text field when not focused 1229 * @param disabledContainerColor the container color for this text field when disabled 1230 * @param errorContainerColor the container color for this text field when in error state 1231 * @param cursorColor the cursor color for this text field 1232 * @param errorCursorColor the cursor color for this text field when in error state 1233 * @param selectionColors the colors used when the input text of this text field is selected 1234 * @param focusedBorderColor the border color for this text field when focused 1235 * @param unfocusedBorderColor the border color for this text field when not focused 1236 * @param disabledBorderColor the border color for this text field when disabled 1237 * @param errorBorderColor the border color for this text field when in error state 1238 * @param focusedLeadingIconColor the leading icon color for this text field when focused 1239 * @param unfocusedLeadingIconColor the leading icon color for this text field when not focused 1240 * @param disabledLeadingIconColor the leading icon color for this text field when disabled 1241 * @param errorLeadingIconColor the leading icon color for this text field when in error state 1242 * @param focusedTrailingIconColor the trailing icon color for this text field when focused 1243 * @param unfocusedTrailingIconColor the trailing icon color for this text field when not 1244 * focused 1245 * @param disabledTrailingIconColor the trailing icon color for this text field when disabled 1246 * @param errorTrailingIconColor the trailing icon color for this text field when in error state 1247 * @param focusedLabelColor the label color for this text field when focused 1248 * @param unfocusedLabelColor the label color for this text field when not focused 1249 * @param disabledLabelColor the label color for this text field when disabled 1250 * @param errorLabelColor the label color for this text field when in error state 1251 * @param focusedPlaceholderColor the placeholder color for this text field when focused 1252 * @param unfocusedPlaceholderColor the placeholder color for this text field when not focused 1253 * @param disabledPlaceholderColor the placeholder color for this text field when disabled 1254 * @param errorPlaceholderColor the placeholder color for this text field when in error state 1255 * @param focusedSupportingTextColor the supporting text color for this text field when focused 1256 * @param unfocusedSupportingTextColor the supporting text color for this text field when not 1257 * focused 1258 * @param disabledSupportingTextColor the supporting text color for this text field when 1259 * disabled 1260 * @param errorSupportingTextColor the supporting text color for this text field when in error 1261 * state 1262 * @param focusedPrefixColor the prefix color for this text field when focused 1263 * @param unfocusedPrefixColor the prefix color for this text field when not focused 1264 * @param disabledPrefixColor the prefix color for this text field when disabled 1265 * @param errorPrefixColor the prefix color for this text field when in error state 1266 * @param focusedSuffixColor the suffix color for this text field when focused 1267 * @param unfocusedSuffixColor the suffix color for this text field when not focused 1268 * @param disabledSuffixColor the suffix color for this text field when disabled 1269 * @param errorSuffixColor the suffix color for this text field when in error state 1270 */ 1271 @Composable 1272 fun colors( 1273 focusedTextColor: Color = Color.Unspecified, 1274 unfocusedTextColor: Color = Color.Unspecified, 1275 disabledTextColor: Color = Color.Unspecified, 1276 errorTextColor: Color = Color.Unspecified, 1277 focusedContainerColor: Color = Color.Unspecified, 1278 unfocusedContainerColor: Color = Color.Unspecified, 1279 disabledContainerColor: Color = Color.Unspecified, 1280 errorContainerColor: Color = Color.Unspecified, 1281 cursorColor: Color = Color.Unspecified, 1282 errorCursorColor: Color = Color.Unspecified, 1283 selectionColors: TextSelectionColors? = null, 1284 focusedBorderColor: Color = Color.Unspecified, 1285 unfocusedBorderColor: Color = Color.Unspecified, 1286 disabledBorderColor: Color = Color.Unspecified, 1287 errorBorderColor: Color = Color.Unspecified, 1288 focusedLeadingIconColor: Color = Color.Unspecified, 1289 unfocusedLeadingIconColor: Color = Color.Unspecified, 1290 disabledLeadingIconColor: Color = Color.Unspecified, 1291 errorLeadingIconColor: Color = Color.Unspecified, 1292 focusedTrailingIconColor: Color = Color.Unspecified, 1293 unfocusedTrailingIconColor: Color = Color.Unspecified, 1294 disabledTrailingIconColor: Color = Color.Unspecified, 1295 errorTrailingIconColor: Color = Color.Unspecified, 1296 focusedLabelColor: Color = Color.Unspecified, 1297 unfocusedLabelColor: Color = Color.Unspecified, 1298 disabledLabelColor: Color = Color.Unspecified, 1299 errorLabelColor: Color = Color.Unspecified, 1300 focusedPlaceholderColor: Color = Color.Unspecified, 1301 unfocusedPlaceholderColor: Color = Color.Unspecified, 1302 disabledPlaceholderColor: Color = Color.Unspecified, 1303 errorPlaceholderColor: Color = Color.Unspecified, 1304 focusedSupportingTextColor: Color = Color.Unspecified, 1305 unfocusedSupportingTextColor: Color = Color.Unspecified, 1306 disabledSupportingTextColor: Color = Color.Unspecified, 1307 errorSupportingTextColor: Color = Color.Unspecified, 1308 focusedPrefixColor: Color = Color.Unspecified, 1309 unfocusedPrefixColor: Color = Color.Unspecified, 1310 disabledPrefixColor: Color = Color.Unspecified, 1311 errorPrefixColor: Color = Color.Unspecified, 1312 focusedSuffixColor: Color = Color.Unspecified, 1313 unfocusedSuffixColor: Color = Color.Unspecified, 1314 disabledSuffixColor: Color = Color.Unspecified, 1315 errorSuffixColor: Color = Color.Unspecified, 1316 ): TextFieldColors = 1317 MaterialTheme.colorScheme.defaultOutlinedTextFieldColors.copy( 1318 focusedTextColor = focusedTextColor, 1319 unfocusedTextColor = unfocusedTextColor, 1320 disabledTextColor = disabledTextColor, 1321 errorTextColor = errorTextColor, 1322 focusedContainerColor = focusedContainerColor, 1323 unfocusedContainerColor = unfocusedContainerColor, 1324 disabledContainerColor = disabledContainerColor, 1325 errorContainerColor = errorContainerColor, 1326 cursorColor = cursorColor, 1327 errorCursorColor = errorCursorColor, 1328 textSelectionColors = selectionColors, 1329 focusedIndicatorColor = focusedBorderColor, 1330 unfocusedIndicatorColor = unfocusedBorderColor, 1331 disabledIndicatorColor = disabledBorderColor, 1332 errorIndicatorColor = errorBorderColor, 1333 focusedLeadingIconColor = focusedLeadingIconColor, 1334 unfocusedLeadingIconColor = unfocusedLeadingIconColor, 1335 disabledLeadingIconColor = disabledLeadingIconColor, 1336 errorLeadingIconColor = errorLeadingIconColor, 1337 focusedTrailingIconColor = focusedTrailingIconColor, 1338 unfocusedTrailingIconColor = unfocusedTrailingIconColor, 1339 disabledTrailingIconColor = disabledTrailingIconColor, 1340 errorTrailingIconColor = errorTrailingIconColor, 1341 focusedLabelColor = focusedLabelColor, 1342 unfocusedLabelColor = unfocusedLabelColor, 1343 disabledLabelColor = disabledLabelColor, 1344 errorLabelColor = errorLabelColor, 1345 focusedPlaceholderColor = focusedPlaceholderColor, 1346 unfocusedPlaceholderColor = unfocusedPlaceholderColor, 1347 disabledPlaceholderColor = disabledPlaceholderColor, 1348 errorPlaceholderColor = errorPlaceholderColor, 1349 focusedSupportingTextColor = focusedSupportingTextColor, 1350 unfocusedSupportingTextColor = unfocusedSupportingTextColor, 1351 disabledSupportingTextColor = disabledSupportingTextColor, 1352 errorSupportingTextColor = errorSupportingTextColor, 1353 focusedPrefixColor = focusedPrefixColor, 1354 unfocusedPrefixColor = unfocusedPrefixColor, 1355 disabledPrefixColor = disabledPrefixColor, 1356 errorPrefixColor = errorPrefixColor, 1357 focusedSuffixColor = focusedSuffixColor, 1358 unfocusedSuffixColor = unfocusedSuffixColor, 1359 disabledSuffixColor = disabledSuffixColor, 1360 errorSuffixColor = errorSuffixColor, 1361 ) 1362 1363 internal val ColorScheme.defaultOutlinedTextFieldColors: TextFieldColors 1364 @Composable 1365 get() { 1366 return defaultOutlinedTextFieldColorsCached?.let { cachedColors -> 1367 val localTextSelectionColors = LocalTextSelectionColors.current 1368 if (cachedColors.textSelectionColors == localTextSelectionColors) { 1369 cachedColors 1370 } else { 1371 cachedColors.copy(textSelectionColors = localTextSelectionColors).also { 1372 defaultOutlinedTextFieldColorsCached = it 1373 } 1374 } 1375 } 1376 ?: TextFieldColors( 1377 focusedTextColor = fromToken(OutlinedTextFieldTokens.FocusInputColor), 1378 unfocusedTextColor = fromToken(OutlinedTextFieldTokens.InputColor), 1379 disabledTextColor = 1380 fromToken(OutlinedTextFieldTokens.DisabledInputColor) 1381 .copy(alpha = OutlinedTextFieldTokens.DisabledInputOpacity), 1382 errorTextColor = fromToken(OutlinedTextFieldTokens.ErrorInputColor), 1383 focusedContainerColor = Color.Transparent, 1384 unfocusedContainerColor = Color.Transparent, 1385 disabledContainerColor = Color.Transparent, 1386 errorContainerColor = Color.Transparent, 1387 cursorColor = fromToken(OutlinedTextFieldTokens.CaretColor), 1388 errorCursorColor = fromToken(OutlinedTextFieldTokens.ErrorFocusCaretColor), 1389 textSelectionColors = LocalTextSelectionColors.current, 1390 focusedIndicatorColor = 1391 fromToken(OutlinedTextFieldTokens.FocusOutlineColor), 1392 unfocusedIndicatorColor = fromToken(OutlinedTextFieldTokens.OutlineColor), 1393 disabledIndicatorColor = 1394 fromToken(OutlinedTextFieldTokens.DisabledOutlineColor) 1395 .copy(alpha = OutlinedTextFieldTokens.DisabledOutlineOpacity), 1396 errorIndicatorColor = fromToken(OutlinedTextFieldTokens.ErrorOutlineColor), 1397 focusedLeadingIconColor = 1398 fromToken(OutlinedTextFieldTokens.FocusLeadingIconColor), 1399 unfocusedLeadingIconColor = 1400 fromToken(OutlinedTextFieldTokens.LeadingIconColor), 1401 disabledLeadingIconColor = 1402 fromToken(OutlinedTextFieldTokens.DisabledLeadingIconColor) 1403 .copy(alpha = OutlinedTextFieldTokens.DisabledLeadingIconOpacity), 1404 errorLeadingIconColor = 1405 fromToken(OutlinedTextFieldTokens.ErrorLeadingIconColor), 1406 focusedTrailingIconColor = 1407 fromToken(OutlinedTextFieldTokens.FocusTrailingIconColor), 1408 unfocusedTrailingIconColor = 1409 fromToken(OutlinedTextFieldTokens.TrailingIconColor), 1410 disabledTrailingIconColor = 1411 fromToken(OutlinedTextFieldTokens.DisabledTrailingIconColor) 1412 .copy(alpha = OutlinedTextFieldTokens.DisabledTrailingIconOpacity), 1413 errorTrailingIconColor = 1414 fromToken(OutlinedTextFieldTokens.ErrorTrailingIconColor), 1415 focusedLabelColor = fromToken(OutlinedTextFieldTokens.FocusLabelColor), 1416 unfocusedLabelColor = fromToken(OutlinedTextFieldTokens.LabelColor), 1417 disabledLabelColor = 1418 fromToken(OutlinedTextFieldTokens.DisabledLabelColor) 1419 .copy(alpha = OutlinedTextFieldTokens.DisabledLabelOpacity), 1420 errorLabelColor = fromToken(OutlinedTextFieldTokens.ErrorLabelColor), 1421 focusedPlaceholderColor = 1422 fromToken(OutlinedTextFieldTokens.InputPlaceholderColor), 1423 unfocusedPlaceholderColor = 1424 fromToken(OutlinedTextFieldTokens.InputPlaceholderColor), 1425 disabledPlaceholderColor = 1426 fromToken(OutlinedTextFieldTokens.DisabledInputColor) 1427 .copy(alpha = OutlinedTextFieldTokens.DisabledInputOpacity), 1428 errorPlaceholderColor = 1429 fromToken(OutlinedTextFieldTokens.InputPlaceholderColor), 1430 focusedSupportingTextColor = 1431 fromToken(OutlinedTextFieldTokens.FocusSupportingColor), 1432 unfocusedSupportingTextColor = 1433 fromToken(OutlinedTextFieldTokens.SupportingColor), 1434 disabledSupportingTextColor = 1435 fromToken(OutlinedTextFieldTokens.DisabledSupportingColor) 1436 .copy(alpha = OutlinedTextFieldTokens.DisabledSupportingOpacity), 1437 errorSupportingTextColor = 1438 fromToken(OutlinedTextFieldTokens.ErrorSupportingColor), 1439 focusedPrefixColor = fromToken(OutlinedTextFieldTokens.InputPrefixColor), 1440 unfocusedPrefixColor = fromToken(OutlinedTextFieldTokens.InputPrefixColor), 1441 disabledPrefixColor = 1442 fromToken(OutlinedTextFieldTokens.InputPrefixColor) 1443 .copy(alpha = OutlinedTextFieldTokens.DisabledInputOpacity), 1444 errorPrefixColor = fromToken(OutlinedTextFieldTokens.InputPrefixColor), 1445 focusedSuffixColor = fromToken(OutlinedTextFieldTokens.InputSuffixColor), 1446 unfocusedSuffixColor = fromToken(OutlinedTextFieldTokens.InputSuffixColor), 1447 disabledSuffixColor = 1448 fromToken(OutlinedTextFieldTokens.InputSuffixColor) 1449 .copy(alpha = OutlinedTextFieldTokens.DisabledInputOpacity), 1450 errorSuffixColor = fromToken(OutlinedTextFieldTokens.InputSuffixColor) 1451 ) 1452 .also { defaultOutlinedTextFieldColorsCached = it } 1453 } 1454 1455 @Deprecated( 1456 message = "Renamed to OutlinedTextFieldDefaults.Container", 1457 replaceWith = 1458 ReplaceWith( 1459 "Container(\n" + 1460 " enabled = enabled,\n" + 1461 " isError = isError,\n" + 1462 " interactionSource = interactionSource,\n" + 1463 " colors = colors,\n" + 1464 " shape = shape,\n" + 1465 " focusedBorderThickness = focusedBorderThickness,\n" + 1466 " unfocusedBorderThickness = unfocusedBorderThickness,\n" + 1467 ")" 1468 ), 1469 level = DeprecationLevel.WARNING 1470 ) 1471 @ExperimentalMaterial3Api 1472 @Composable ContainerBoxnull1473 fun ContainerBox( 1474 enabled: Boolean, 1475 isError: Boolean, 1476 interactionSource: InteractionSource, 1477 colors: TextFieldColors = colors(), 1478 shape: Shape = OutlinedTextFieldDefaults.shape, 1479 focusedBorderThickness: Dp = FocusedBorderThickness, 1480 unfocusedBorderThickness: Dp = UnfocusedBorderThickness, 1481 ) = 1482 Container( 1483 enabled = enabled, 1484 isError = isError, 1485 interactionSource = interactionSource, 1486 modifier = Modifier, 1487 colors = colors, 1488 shape = shape, 1489 focusedBorderThickness = focusedBorderThickness, 1490 unfocusedBorderThickness = unfocusedBorderThickness, 1491 ) 1492 } 1493 1494 /** 1495 * Represents the colors of the input text, container, and content (including label, placeholder, 1496 * leading and trailing icons) used in a text field in different states. 1497 * 1498 * @param focusedTextColor the color used for the input text of this text field when focused 1499 * @param unfocusedTextColor the color used for the input text of this text field when not focused 1500 * @param disabledTextColor the color used for the input text of this text field when disabled 1501 * @param errorTextColor the color used for the input text of this text field when in error state 1502 * @param focusedContainerColor the container color for this text field when focused 1503 * @param unfocusedContainerColor the container color for this text field when not focused 1504 * @param disabledContainerColor the container color for this text field when disabled 1505 * @param errorContainerColor the container color for this text field when in error state 1506 * @param cursorColor the cursor color for this text field 1507 * @param errorCursorColor the cursor color for this text field when in error state 1508 * @param textSelectionColors the colors used when the input text of this text field is selected 1509 * @param focusedIndicatorColor the indicator color for this text field when focused 1510 * @param unfocusedIndicatorColor the indicator color for this text field when not focused 1511 * @param disabledIndicatorColor the indicator color for this text field when disabled 1512 * @param errorIndicatorColor the indicator color for this text field when in error state 1513 * @param focusedLeadingIconColor the leading icon color for this text field when focused 1514 * @param unfocusedLeadingIconColor the leading icon color for this text field when not focused 1515 * @param disabledLeadingIconColor the leading icon color for this text field when disabled 1516 * @param errorLeadingIconColor the leading icon color for this text field when in error state 1517 * @param focusedTrailingIconColor the trailing icon color for this text field when focused 1518 * @param unfocusedTrailingIconColor the trailing icon color for this text field when not focused 1519 * @param disabledTrailingIconColor the trailing icon color for this text field when disabled 1520 * @param errorTrailingIconColor the trailing icon color for this text field when in error state 1521 * @param focusedLabelColor the label color for this text field when focused 1522 * @param unfocusedLabelColor the label color for this text field when not focused 1523 * @param disabledLabelColor the label color for this text field when disabled 1524 * @param errorLabelColor the label color for this text field when in error state 1525 * @param focusedPlaceholderColor the placeholder color for this text field when focused 1526 * @param unfocusedPlaceholderColor the placeholder color for this text field when not focused 1527 * @param disabledPlaceholderColor the placeholder color for this text field when disabled 1528 * @param errorPlaceholderColor the placeholder color for this text field when in error state 1529 * @param focusedSupportingTextColor the supporting text color for this text field when focused 1530 * @param unfocusedSupportingTextColor the supporting text color for this text field when not 1531 * focused 1532 * @param disabledSupportingTextColor the supporting text color for this text field when disabled 1533 * @param errorSupportingTextColor the supporting text color for this text field when in error state 1534 * @param focusedPrefixColor the prefix color for this text field when focused 1535 * @param unfocusedPrefixColor the prefix color for this text field when not focused 1536 * @param disabledPrefixColor the prefix color for this text field when disabled 1537 * @param errorPrefixColor the prefix color for this text field when in error state 1538 * @param focusedSuffixColor the suffix color for this text field when focused 1539 * @param unfocusedSuffixColor the suffix color for this text field when not focused 1540 * @param disabledSuffixColor the suffix color for this text field when disabled 1541 * @param errorSuffixColor the suffix color for this text field when in error state 1542 * @constructor create an instance with arbitrary colors. See [TextFieldDefaults.colors] for the 1543 * default colors used in [TextField]. See [OutlinedTextFieldDefaults.colors] for the default 1544 * colors used in [OutlinedTextField]. 1545 */ 1546 @Immutable 1547 class TextFieldColors 1548 constructor( 1549 val focusedTextColor: Color, 1550 val unfocusedTextColor: Color, 1551 val disabledTextColor: Color, 1552 val errorTextColor: Color, 1553 val focusedContainerColor: Color, 1554 val unfocusedContainerColor: Color, 1555 val disabledContainerColor: Color, 1556 val errorContainerColor: Color, 1557 val cursorColor: Color, 1558 val errorCursorColor: Color, 1559 val textSelectionColors: TextSelectionColors, 1560 val focusedIndicatorColor: Color, 1561 val unfocusedIndicatorColor: Color, 1562 val disabledIndicatorColor: Color, 1563 val errorIndicatorColor: Color, 1564 val focusedLeadingIconColor: Color, 1565 val unfocusedLeadingIconColor: Color, 1566 val disabledLeadingIconColor: Color, 1567 val errorLeadingIconColor: Color, 1568 val focusedTrailingIconColor: Color, 1569 val unfocusedTrailingIconColor: Color, 1570 val disabledTrailingIconColor: Color, 1571 val errorTrailingIconColor: Color, 1572 val focusedLabelColor: Color, 1573 val unfocusedLabelColor: Color, 1574 val disabledLabelColor: Color, 1575 val errorLabelColor: Color, 1576 val focusedPlaceholderColor: Color, 1577 val unfocusedPlaceholderColor: Color, 1578 val disabledPlaceholderColor: Color, 1579 val errorPlaceholderColor: Color, 1580 val focusedSupportingTextColor: Color, 1581 val unfocusedSupportingTextColor: Color, 1582 val disabledSupportingTextColor: Color, 1583 val errorSupportingTextColor: Color, 1584 val focusedPrefixColor: Color, 1585 val unfocusedPrefixColor: Color, 1586 val disabledPrefixColor: Color, 1587 val errorPrefixColor: Color, 1588 val focusedSuffixColor: Color, 1589 val unfocusedSuffixColor: Color, 1590 val disabledSuffixColor: Color, 1591 val errorSuffixColor: Color, 1592 ) { 1593 1594 /** 1595 * Returns a copy of this ChipColors, optionally overriding some of the values. This uses the 1596 * Color.Unspecified to mean “use the value from the source” 1597 */ 1598 fun copy( 1599 focusedTextColor: Color = this.focusedTextColor, 1600 unfocusedTextColor: Color = this.unfocusedTextColor, 1601 disabledTextColor: Color = this.disabledTextColor, 1602 errorTextColor: Color = this.errorTextColor, 1603 focusedContainerColor: Color = this.focusedContainerColor, 1604 unfocusedContainerColor: Color = this.unfocusedContainerColor, 1605 disabledContainerColor: Color = this.disabledContainerColor, 1606 errorContainerColor: Color = this.errorContainerColor, 1607 cursorColor: Color = this.cursorColor, 1608 errorCursorColor: Color = this.errorCursorColor, 1609 textSelectionColors: TextSelectionColors? = this.textSelectionColors, 1610 focusedIndicatorColor: Color = this.focusedIndicatorColor, 1611 unfocusedIndicatorColor: Color = this.unfocusedIndicatorColor, 1612 disabledIndicatorColor: Color = this.disabledIndicatorColor, 1613 errorIndicatorColor: Color = this.errorIndicatorColor, 1614 focusedLeadingIconColor: Color = this.focusedLeadingIconColor, 1615 unfocusedLeadingIconColor: Color = this.unfocusedLeadingIconColor, 1616 disabledLeadingIconColor: Color = this.disabledLeadingIconColor, 1617 errorLeadingIconColor: Color = this.errorLeadingIconColor, 1618 focusedTrailingIconColor: Color = this.focusedTrailingIconColor, 1619 unfocusedTrailingIconColor: Color = this.unfocusedTrailingIconColor, 1620 disabledTrailingIconColor: Color = this.disabledTrailingIconColor, 1621 errorTrailingIconColor: Color = this.errorTrailingIconColor, 1622 focusedLabelColor: Color = this.focusedLabelColor, 1623 unfocusedLabelColor: Color = this.unfocusedLabelColor, 1624 disabledLabelColor: Color = this.disabledLabelColor, 1625 errorLabelColor: Color = this.errorLabelColor, 1626 focusedPlaceholderColor: Color = this.focusedPlaceholderColor, 1627 unfocusedPlaceholderColor: Color = this.unfocusedPlaceholderColor, 1628 disabledPlaceholderColor: Color = this.disabledPlaceholderColor, 1629 errorPlaceholderColor: Color = this.errorPlaceholderColor, 1630 focusedSupportingTextColor: Color = this.focusedSupportingTextColor, 1631 unfocusedSupportingTextColor: Color = this.unfocusedSupportingTextColor, 1632 disabledSupportingTextColor: Color = this.disabledSupportingTextColor, 1633 errorSupportingTextColor: Color = this.errorSupportingTextColor, 1634 focusedPrefixColor: Color = this.focusedPrefixColor, 1635 unfocusedPrefixColor: Color = this.unfocusedPrefixColor, 1636 disabledPrefixColor: Color = this.disabledPrefixColor, 1637 errorPrefixColor: Color = this.errorPrefixColor, 1638 focusedSuffixColor: Color = this.focusedSuffixColor, 1639 unfocusedSuffixColor: Color = this.unfocusedSuffixColor, 1640 disabledSuffixColor: Color = this.disabledSuffixColor, 1641 errorSuffixColor: Color = this.errorSuffixColor, 1642 ) = 1643 TextFieldColors( 1644 focusedTextColor.takeOrElse { this.focusedTextColor }, 1645 unfocusedTextColor.takeOrElse { this.unfocusedTextColor }, 1646 disabledTextColor.takeOrElse { this.disabledTextColor }, 1647 errorTextColor.takeOrElse { this.errorTextColor }, 1648 focusedContainerColor.takeOrElse { this.focusedContainerColor }, 1649 unfocusedContainerColor.takeOrElse { this.unfocusedContainerColor }, 1650 disabledContainerColor.takeOrElse { this.disabledContainerColor }, 1651 errorContainerColor.takeOrElse { this.errorContainerColor }, 1652 cursorColor.takeOrElse { this.cursorColor }, 1653 errorCursorColor.takeOrElse { this.errorCursorColor }, 1654 textSelectionColors.takeOrElse { this.textSelectionColors }, 1655 focusedIndicatorColor.takeOrElse { this.focusedIndicatorColor }, 1656 unfocusedIndicatorColor.takeOrElse { this.unfocusedIndicatorColor }, 1657 disabledIndicatorColor.takeOrElse { this.disabledIndicatorColor }, 1658 errorIndicatorColor.takeOrElse { this.errorIndicatorColor }, 1659 focusedLeadingIconColor.takeOrElse { this.focusedLeadingIconColor }, 1660 unfocusedLeadingIconColor.takeOrElse { this.unfocusedLeadingIconColor }, 1661 disabledLeadingIconColor.takeOrElse { this.disabledLeadingIconColor }, 1662 errorLeadingIconColor.takeOrElse { this.errorLeadingIconColor }, 1663 focusedTrailingIconColor.takeOrElse { this.focusedTrailingIconColor }, 1664 unfocusedTrailingIconColor.takeOrElse { this.unfocusedTrailingIconColor }, 1665 disabledTrailingIconColor.takeOrElse { this.disabledTrailingIconColor }, 1666 errorTrailingIconColor.takeOrElse { this.errorTrailingIconColor }, 1667 focusedLabelColor.takeOrElse { this.focusedLabelColor }, 1668 unfocusedLabelColor.takeOrElse { this.unfocusedLabelColor }, 1669 disabledLabelColor.takeOrElse { this.disabledLabelColor }, 1670 errorLabelColor.takeOrElse { this.errorLabelColor }, 1671 focusedPlaceholderColor.takeOrElse { this.focusedPlaceholderColor }, 1672 unfocusedPlaceholderColor.takeOrElse { this.unfocusedPlaceholderColor }, 1673 disabledPlaceholderColor.takeOrElse { this.disabledPlaceholderColor }, 1674 errorPlaceholderColor.takeOrElse { this.errorPlaceholderColor }, 1675 focusedSupportingTextColor.takeOrElse { this.focusedSupportingTextColor }, 1676 unfocusedSupportingTextColor.takeOrElse { this.unfocusedSupportingTextColor }, 1677 disabledSupportingTextColor.takeOrElse { this.disabledSupportingTextColor }, 1678 errorSupportingTextColor.takeOrElse { this.errorSupportingTextColor }, 1679 focusedPrefixColor.takeOrElse { this.focusedPrefixColor }, 1680 unfocusedPrefixColor.takeOrElse { this.unfocusedPrefixColor }, 1681 disabledPrefixColor.takeOrElse { this.disabledPrefixColor }, 1682 errorPrefixColor.takeOrElse { this.errorPrefixColor }, 1683 focusedSuffixColor.takeOrElse { this.focusedSuffixColor }, 1684 unfocusedSuffixColor.takeOrElse { this.unfocusedSuffixColor }, 1685 disabledSuffixColor.takeOrElse { this.disabledSuffixColor }, 1686 errorSuffixColor.takeOrElse { this.errorSuffixColor }, 1687 ) 1688 1689 internal fun TextSelectionColors?.takeOrElse( 1690 block: () -> TextSelectionColors 1691 ): TextSelectionColors = this ?: block() 1692 1693 /** 1694 * Represents the color used for the leading icon of this text field. 1695 * 1696 * @param enabled whether the text field is enabled 1697 * @param isError whether the text field's current value is in error 1698 * @param focused whether the text field is in focus 1699 */ 1700 @Stable 1701 internal fun leadingIconColor( 1702 enabled: Boolean, 1703 isError: Boolean, 1704 focused: Boolean, 1705 ): Color = 1706 when { 1707 !enabled -> disabledLeadingIconColor 1708 isError -> errorLeadingIconColor 1709 focused -> focusedLeadingIconColor 1710 else -> unfocusedLeadingIconColor 1711 } 1712 1713 /** 1714 * Represents the color used for the trailing icon of this text field. 1715 * 1716 * @param enabled whether the text field is enabled 1717 * @param isError whether the text field's current value is in error 1718 * @param focused whether the text field is in focus 1719 */ 1720 @Stable 1721 internal fun trailingIconColor( 1722 enabled: Boolean, 1723 isError: Boolean, 1724 focused: Boolean, 1725 ): Color = 1726 when { 1727 !enabled -> disabledTrailingIconColor 1728 isError -> errorTrailingIconColor 1729 focused -> focusedTrailingIconColor 1730 else -> unfocusedTrailingIconColor 1731 } 1732 1733 /** 1734 * Represents the color used for the border indicator of this text field. 1735 * 1736 * @param enabled whether the text field is enabled 1737 * @param isError whether the text field's current value is in error 1738 * @param focused whether the text field is in focus 1739 */ 1740 @Stable 1741 internal fun indicatorColor( 1742 enabled: Boolean, 1743 isError: Boolean, 1744 focused: Boolean, 1745 ): Color = 1746 when { 1747 !enabled -> disabledIndicatorColor 1748 isError -> errorIndicatorColor 1749 focused -> focusedIndicatorColor 1750 else -> unfocusedIndicatorColor 1751 } 1752 1753 /** 1754 * Represents the container color for this text field. 1755 * 1756 * @param enabled whether the text field is enabled 1757 * @param isError whether the text field's current value is in error 1758 * @param focused whether the text field is in focus 1759 */ 1760 @Stable 1761 internal fun containerColor( 1762 enabled: Boolean, 1763 isError: Boolean, 1764 focused: Boolean, 1765 ): Color = 1766 when { 1767 !enabled -> disabledContainerColor 1768 isError -> errorContainerColor 1769 focused -> focusedContainerColor 1770 else -> unfocusedContainerColor 1771 } 1772 1773 /** 1774 * Represents the color used for the placeholder of this text field. 1775 * 1776 * @param enabled whether the text field is enabled 1777 * @param isError whether the text field's current value is in error 1778 * @param focused whether the text field is in focus 1779 */ 1780 @Stable 1781 internal fun placeholderColor( 1782 enabled: Boolean, 1783 isError: Boolean, 1784 focused: Boolean, 1785 ): Color = 1786 when { 1787 !enabled -> disabledPlaceholderColor 1788 isError -> errorPlaceholderColor 1789 focused -> focusedPlaceholderColor 1790 else -> unfocusedPlaceholderColor 1791 } 1792 1793 /** 1794 * Represents the color used for the label of this text field. 1795 * 1796 * @param enabled whether the text field is enabled 1797 * @param isError whether the text field's current value is in error 1798 * @param focused whether the text field is in focus 1799 */ 1800 @Stable 1801 internal fun labelColor( 1802 enabled: Boolean, 1803 isError: Boolean, 1804 focused: Boolean, 1805 ): Color = 1806 when { 1807 !enabled -> disabledLabelColor 1808 isError -> errorLabelColor 1809 focused -> focusedLabelColor 1810 else -> unfocusedLabelColor 1811 } 1812 1813 /** 1814 * Represents the color used for the input field of this text field. 1815 * 1816 * @param enabled whether the text field is enabled 1817 * @param isError whether the text field's current value is in error 1818 * @param focused whether the text field is in focus 1819 */ 1820 @Stable 1821 internal fun textColor( 1822 enabled: Boolean, 1823 isError: Boolean, 1824 focused: Boolean, 1825 ): Color = 1826 when { 1827 !enabled -> disabledTextColor 1828 isError -> errorTextColor 1829 focused -> focusedTextColor 1830 else -> unfocusedTextColor 1831 } 1832 1833 /** 1834 * Represents the colors used for the supporting text of this text field. 1835 * 1836 * @param enabled whether the text field is enabled 1837 * @param isError whether the text field's current value is in error 1838 * @param focused whether the text field is in focus 1839 */ 1840 @Stable 1841 internal fun supportingTextColor( 1842 enabled: Boolean, 1843 isError: Boolean, 1844 focused: Boolean, 1845 ): Color = 1846 when { 1847 !enabled -> disabledSupportingTextColor 1848 isError -> errorSupportingTextColor 1849 focused -> focusedSupportingTextColor 1850 else -> unfocusedSupportingTextColor 1851 } 1852 1853 /** 1854 * Represents the color used for the prefix of this text field. 1855 * 1856 * @param enabled whether the text field is enabled 1857 * @param isError whether the text field's current value is in error 1858 * @param focused whether the text field is in focus 1859 */ 1860 @Stable 1861 internal fun prefixColor( 1862 enabled: Boolean, 1863 isError: Boolean, 1864 focused: Boolean, 1865 ): Color = 1866 when { 1867 !enabled -> disabledPrefixColor 1868 isError -> errorPrefixColor 1869 focused -> focusedPrefixColor 1870 else -> unfocusedPrefixColor 1871 } 1872 1873 /** 1874 * Represents the color used for the suffix of this text field. 1875 * 1876 * @param enabled whether the text field is enabled 1877 * @param isError whether the text field's current value is in error 1878 * @param focused whether the text field is in focus 1879 */ 1880 @Stable 1881 internal fun suffixColor( 1882 enabled: Boolean, 1883 isError: Boolean, 1884 focused: Boolean, 1885 ): Color = 1886 when { 1887 !enabled -> disabledSuffixColor 1888 isError -> errorSuffixColor 1889 focused -> focusedSuffixColor 1890 else -> unfocusedSuffixColor 1891 } 1892 1893 /** 1894 * Represents the color used for the cursor of this text field. 1895 * 1896 * @param isError whether the text field's current value is in error 1897 */ 1898 @Stable 1899 internal fun cursorColor(isError: Boolean): Color = 1900 if (isError) errorCursorColor else cursorColor 1901 1902 override fun equals(other: Any?): Boolean { 1903 if (this === other) return true 1904 if (other == null || other !is TextFieldColors) return false 1905 1906 if (focusedTextColor != other.focusedTextColor) return false 1907 if (unfocusedTextColor != other.unfocusedTextColor) return false 1908 if (disabledTextColor != other.disabledTextColor) return false 1909 if (errorTextColor != other.errorTextColor) return false 1910 if (focusedContainerColor != other.focusedContainerColor) return false 1911 if (unfocusedContainerColor != other.unfocusedContainerColor) return false 1912 if (disabledContainerColor != other.disabledContainerColor) return false 1913 if (errorContainerColor != other.errorContainerColor) return false 1914 if (cursorColor != other.cursorColor) return false 1915 if (errorCursorColor != other.errorCursorColor) return false 1916 if (textSelectionColors != other.textSelectionColors) return false 1917 if (focusedIndicatorColor != other.focusedIndicatorColor) return false 1918 if (unfocusedIndicatorColor != other.unfocusedIndicatorColor) return false 1919 if (disabledIndicatorColor != other.disabledIndicatorColor) return false 1920 if (errorIndicatorColor != other.errorIndicatorColor) return false 1921 if (focusedLeadingIconColor != other.focusedLeadingIconColor) return false 1922 if (unfocusedLeadingIconColor != other.unfocusedLeadingIconColor) return false 1923 if (disabledLeadingIconColor != other.disabledLeadingIconColor) return false 1924 if (errorLeadingIconColor != other.errorLeadingIconColor) return false 1925 if (focusedTrailingIconColor != other.focusedTrailingIconColor) return false 1926 if (unfocusedTrailingIconColor != other.unfocusedTrailingIconColor) return false 1927 if (disabledTrailingIconColor != other.disabledTrailingIconColor) return false 1928 if (errorTrailingIconColor != other.errorTrailingIconColor) return false 1929 if (focusedLabelColor != other.focusedLabelColor) return false 1930 if (unfocusedLabelColor != other.unfocusedLabelColor) return false 1931 if (disabledLabelColor != other.disabledLabelColor) return false 1932 if (errorLabelColor != other.errorLabelColor) return false 1933 if (focusedPlaceholderColor != other.focusedPlaceholderColor) return false 1934 if (unfocusedPlaceholderColor != other.unfocusedPlaceholderColor) return false 1935 if (disabledPlaceholderColor != other.disabledPlaceholderColor) return false 1936 if (errorPlaceholderColor != other.errorPlaceholderColor) return false 1937 if (focusedSupportingTextColor != other.focusedSupportingTextColor) return false 1938 if (unfocusedSupportingTextColor != other.unfocusedSupportingTextColor) return false 1939 if (disabledSupportingTextColor != other.disabledSupportingTextColor) return false 1940 if (errorSupportingTextColor != other.errorSupportingTextColor) return false 1941 if (focusedPrefixColor != other.focusedPrefixColor) return false 1942 if (unfocusedPrefixColor != other.unfocusedPrefixColor) return false 1943 if (disabledPrefixColor != other.disabledPrefixColor) return false 1944 if (errorPrefixColor != other.errorPrefixColor) return false 1945 if (focusedSuffixColor != other.focusedSuffixColor) return false 1946 if (unfocusedSuffixColor != other.unfocusedSuffixColor) return false 1947 if (disabledSuffixColor != other.disabledSuffixColor) return false 1948 if (errorSuffixColor != other.errorSuffixColor) return false 1949 1950 return true 1951 } 1952 1953 override fun hashCode(): Int { 1954 var result = focusedTextColor.hashCode() 1955 result = 31 * result + unfocusedTextColor.hashCode() 1956 result = 31 * result + disabledTextColor.hashCode() 1957 result = 31 * result + errorTextColor.hashCode() 1958 result = 31 * result + focusedContainerColor.hashCode() 1959 result = 31 * result + unfocusedContainerColor.hashCode() 1960 result = 31 * result + disabledContainerColor.hashCode() 1961 result = 31 * result + errorContainerColor.hashCode() 1962 result = 31 * result + cursorColor.hashCode() 1963 result = 31 * result + errorCursorColor.hashCode() 1964 result = 31 * result + textSelectionColors.hashCode() 1965 result = 31 * result + focusedIndicatorColor.hashCode() 1966 result = 31 * result + unfocusedIndicatorColor.hashCode() 1967 result = 31 * result + disabledIndicatorColor.hashCode() 1968 result = 31 * result + errorIndicatorColor.hashCode() 1969 result = 31 * result + focusedLeadingIconColor.hashCode() 1970 result = 31 * result + unfocusedLeadingIconColor.hashCode() 1971 result = 31 * result + disabledLeadingIconColor.hashCode() 1972 result = 31 * result + errorLeadingIconColor.hashCode() 1973 result = 31 * result + focusedTrailingIconColor.hashCode() 1974 result = 31 * result + unfocusedTrailingIconColor.hashCode() 1975 result = 31 * result + disabledTrailingIconColor.hashCode() 1976 result = 31 * result + errorTrailingIconColor.hashCode() 1977 result = 31 * result + focusedLabelColor.hashCode() 1978 result = 31 * result + unfocusedLabelColor.hashCode() 1979 result = 31 * result + disabledLabelColor.hashCode() 1980 result = 31 * result + errorLabelColor.hashCode() 1981 result = 31 * result + focusedPlaceholderColor.hashCode() 1982 result = 31 * result + unfocusedPlaceholderColor.hashCode() 1983 result = 31 * result + disabledPlaceholderColor.hashCode() 1984 result = 31 * result + errorPlaceholderColor.hashCode() 1985 result = 31 * result + focusedSupportingTextColor.hashCode() 1986 result = 31 * result + unfocusedSupportingTextColor.hashCode() 1987 result = 31 * result + disabledSupportingTextColor.hashCode() 1988 result = 31 * result + errorSupportingTextColor.hashCode() 1989 result = 31 * result + focusedPrefixColor.hashCode() 1990 result = 31 * result + unfocusedPrefixColor.hashCode() 1991 result = 31 * result + disabledPrefixColor.hashCode() 1992 result = 31 * result + errorPrefixColor.hashCode() 1993 result = 31 * result + focusedSuffixColor.hashCode() 1994 result = 31 * result + unfocusedSuffixColor.hashCode() 1995 result = 31 * result + disabledSuffixColor.hashCode() 1996 result = 31 * result + errorSuffixColor.hashCode() 1997 return result 1998 } 1999 } 2000 2001 /** The position of the label with respect to the text field. */ 2002 abstract class TextFieldLabelPosition private constructor() { 2003 /** 2004 * The default label position according to the Material specification. 2005 * 2006 * For [TextField], the label is positioned inside the text field container. For 2007 * [OutlinedTextField], the label is positioned inside the text field container when expanded 2008 * and cuts into the border when minimized. 2009 * 2010 * @param alwaysMinimize Whether to always keep the label of the text field minimized. If 2011 * `false`, the label will expand to occupy the input area when the text field is unfocused 2012 * and empty. If `true`, this allows displaying the placeholder, prefix, and suffix alongside 2013 * the label when the text field is unfocused and empty. 2014 * @param minimizedAlignment The horizontal alignment of the label when it is minimized. 2015 * @param expandedAlignment The horizontal alignment of the label when it is expanded. 2016 */ 2017 class Attached( 2018 @get:Suppress("GetterSetterNames") val alwaysMinimize: Boolean = false, 2019 val minimizedAlignment: Alignment.Horizontal = Alignment.Start, 2020 val expandedAlignment: Alignment.Horizontal = Alignment.Start, 2021 ) : TextFieldLabelPosition() { equalsnull2022 override fun equals(other: Any?): Boolean { 2023 if (this === other) return true 2024 if (other !is Attached) return false 2025 2026 if (alwaysMinimize != other.alwaysMinimize) return false 2027 if (minimizedAlignment != other.minimizedAlignment) return false 2028 if (expandedAlignment != other.expandedAlignment) return false 2029 2030 return true 2031 } 2032 hashCodenull2033 override fun hashCode(): Int { 2034 var result = alwaysMinimize.hashCode() 2035 result = 31 * result + minimizedAlignment.hashCode() 2036 result = 31 * result + expandedAlignment.hashCode() 2037 return result 2038 } 2039 toStringnull2040 override fun toString(): String { 2041 return "Attached(" + 2042 "alwaysMinimize=$alwaysMinimize, " + 2043 "minimizedAlignment=$minimizedAlignment, " + 2044 "expandedAlignment=$expandedAlignment" + 2045 ")" 2046 } 2047 } 2048 2049 /** 2050 * The label is positioned above and outside the text field container. This results in the label 2051 * always being minimized. 2052 * 2053 * @param alignment The horizontal alignment of the label. 2054 */ 2055 class Above(val alignment: Alignment.Horizontal = Alignment.Start) : TextFieldLabelPosition() { equalsnull2056 override fun equals(other: Any?): Boolean { 2057 if (this === other) return true 2058 if (other !is Above) return false 2059 2060 return alignment == other.alignment 2061 } 2062 hashCodenull2063 override fun hashCode(): Int { 2064 return alignment.hashCode() 2065 } 2066 toStringnull2067 override fun toString(): String = "Above(alignment=$alignment)" 2068 } 2069 } 2070 2071 /** Scope for the label of a [TextField] or [OutlinedTextField]. */ 2072 @Stable 2073 interface TextFieldLabelScope { 2074 /** 2075 * The animation progress of a label between its expanded and minimized sizes, where 0 2076 * represents an expanded label and 1 represents a minimized label. 2077 * 2078 * Label animation is handled by the framework when using a component that reads from 2079 * [LocalTextStyle], such as the default [Text]. This [labelMinimizedProgress] value can be used 2080 * to coordinate other animations in conjunction with the default animation. 2081 */ 2082 @get:FloatRange(from = 0.0, to = 1.0) val labelMinimizedProgress: Float 2083 } 2084