1 /*
2 * Copyright 2021 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 package androidx.wear.compose.material
17
18 import androidx.compose.foundation.BorderStroke
19 import androidx.compose.foundation.border
20 import androidx.compose.foundation.clickable
21 import androidx.compose.foundation.interaction.Interaction
22 import androidx.compose.foundation.interaction.MutableInteractionSource
23 import androidx.compose.foundation.layout.Box
24 import androidx.compose.foundation.layout.BoxScope
25 import androidx.compose.foundation.layout.Column
26 import androidx.compose.foundation.layout.IntrinsicSize
27 import androidx.compose.foundation.layout.PaddingValues
28 import androidx.compose.foundation.layout.Row
29 import androidx.compose.foundation.layout.RowScope
30 import androidx.compose.foundation.layout.Spacer
31 import androidx.compose.foundation.layout.defaultMinSize
32 import androidx.compose.foundation.layout.fillMaxHeight
33 import androidx.compose.foundation.layout.fillMaxSize
34 import androidx.compose.foundation.layout.height
35 import androidx.compose.foundation.layout.padding
36 import androidx.compose.foundation.layout.size
37 import androidx.compose.foundation.layout.width
38 import androidx.compose.foundation.layout.wrapContentSize
39 import androidx.compose.runtime.Composable
40 import androidx.compose.runtime.Immutable
41 import androidx.compose.runtime.Stable
42 import androidx.compose.runtime.State
43 import androidx.compose.runtime.remember
44 import androidx.compose.runtime.rememberUpdatedState
45 import androidx.compose.ui.Alignment
46 import androidx.compose.ui.Modifier
47 import androidx.compose.ui.draw.clip
48 import androidx.compose.ui.draw.paint
49 import androidx.compose.ui.graphics.Brush
50 import androidx.compose.ui.graphics.Color
51 import androidx.compose.ui.graphics.Shape
52 import androidx.compose.ui.graphics.compositeOver
53 import androidx.compose.ui.graphics.painter.BrushPainter
54 import androidx.compose.ui.graphics.painter.ColorPainter
55 import androidx.compose.ui.graphics.painter.Painter
56 import androidx.compose.ui.layout.ContentScale
57 import androidx.compose.ui.platform.LocalLayoutDirection
58 import androidx.compose.ui.semantics.Role
59 import androidx.compose.ui.text.TextStyle
60 import androidx.compose.ui.unit.Dp
61 import androidx.compose.ui.unit.LayoutDirection
62 import androidx.compose.ui.unit.dp
63 import androidx.wear.compose.materialcore.ImageWithScrimPainter
64
65 /**
66 * Base level Wear Material [Chip] that offers a single slot to take any content.
67 *
68 * Is used as the container for more opinionated [Chip] components that take specific content such
69 * as icons and labels.
70 *
71 * The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
72 * of [Typography.button] style. The [Chip] can have an icon or image horizontally parallel to the
73 * two lines of text. With localisation and/or large font sizes, the [Chip] height adjusts to
74 * accommodate the contents.
75 *
76 * The [Chip] can have different styles with configurable content colors, background colors
77 * including gradients, these are provided by [ChipColors] implementations.
78 *
79 * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
80 * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
81 * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
82 *
83 * Chips can be enabled or disabled. A disabled chip will not respond to click events.
84 *
85 * For more information, see the
86 * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
87 *
88 * @param onClick Will be called when the user clicks the chip
89 * @param colors [ChipColors] that will be used to resolve the background and content color for this
90 * chip in different states. See [ChipDefaults.chipColors].
91 * @param modifier Modifier to be applied to the chip
92 * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
93 * clickable
94 * @param contentPadding The spacing values to apply internally between the container and the
95 * content
96 * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
97 * shape is a key characteristic of the Wear Material Theme
98 * @param interactionSource The [MutableInteractionSource] representing the stream of [Interaction]s
99 * for this Chip. You can create and pass in your own remembered [MutableInteractionSource] if you
100 * want to observe [Interaction]s and customize the appearance / behavior of this Chip in
101 * different [Interaction]s.
102 * @param role The type of user interface element. Accessibility services might use this to describe
103 * the element or do customizations
104 */
105 @Deprecated(
106 "This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
107 "A newer overload is available with an additional border parameter.",
108 level = DeprecationLevel.HIDDEN
109 )
110 @Composable
Chipnull111 public fun Chip(
112 onClick: () -> Unit,
113 colors: ChipColors,
114 modifier: Modifier = Modifier,
115 enabled: Boolean = true,
116 contentPadding: PaddingValues = ChipDefaults.ContentPadding,
117 shape: Shape = MaterialTheme.shapes.large,
118 interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
119 role: Role? = Role.Button,
120 content: @Composable RowScope.() -> Unit,
121 ): Unit =
122 Chip(
123 onClick = onClick,
124 colors = colors,
125 border = ChipDefaults.chipBorder(),
126 modifier = modifier,
127 enabled = enabled,
128 contentPadding = contentPadding,
129 shape = shape,
130 interactionSource = interactionSource,
131 role = role,
132 content = content
133 )
134
135 /**
136 * Base level Wear Material [Chip] that offers a single slot to take any content.
137 *
138 * Is used as the container for more opinionated [Chip] components that take specific content such
139 * as icons and labels.
140 *
141 * The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
142 * of [Typography.button] style. The [Chip] can have an icon or image horizontally parallel to the
143 * two lines of text. With localisation and/or large font sizes, the [Chip] height adjusts to
144 * accommodate the contents.
145 *
146 * The [Chip] can have different styles with configurable content colors, background colors
147 * including gradients, these are provided by [ChipColors] implementations.
148 *
149 * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
150 * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
151 * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
152 *
153 * Chips can be enabled or disabled. A disabled chip will not respond to click events.
154 *
155 * For more information, see the
156 * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
157 *
158 * @param onClick Will be called when the user clicks the chip
159 * @param colors [ChipColors] that will be used to resolve the background and content color for this
160 * chip in different states. See [ChipDefaults.chipColors].
161 * @param border [ChipBorder] that will be used to resolve the border for this chip in different
162 * states. See [ChipDefaults.chipBorder].
163 * @param modifier Modifier to be applied to the chip
164 * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
165 * clickable
166 * @param contentPadding The spacing values to apply internally between the container and the
167 * content
168 * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
169 * shape is a key characteristic of the Wear Material Theme
170 * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
171 * emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
172 * preview the chip in different states. Note that if `null` is provided, interactions will still
173 * happen internally.
174 * @param role The type of user interface element. Accessibility services might use this to describe
175 * the element or do customizations
176 * @param content Slot for composable body content displayed on the Chip
177 */
178 @Composable
Chipnull179 public fun Chip(
180 onClick: () -> Unit,
181 colors: ChipColors,
182 border: ChipBorder,
183 modifier: Modifier = Modifier,
184 enabled: Boolean = true,
185 contentPadding: PaddingValues = ChipDefaults.ContentPadding,
186 shape: Shape = MaterialTheme.shapes.large,
187 interactionSource: MutableInteractionSource? = null,
188 role: Role? = Role.Button,
189 content: @Composable RowScope.() -> Unit,
190 ) {
191 ChipImpl(
192 onClick = onClick,
193 colors = colors,
194 border = border,
195 modifier = modifier.chipSizeModifier(),
196 enabled = enabled,
197 contentPadding = contentPadding,
198 shape = shape,
199 interactionSource = interactionSource,
200 role = role,
201 content = content
202 )
203 }
204
205 /**
206 * Wear Material [Chip] that offers three slots and a specific layout for an icon, label and
207 * secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with the icon,
208 * if provided, at the start of a row, with a column next containing the two label slots.
209 *
210 * The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
211 * of [Typography.button] style. If no secondary label is provided then the label can be two lines
212 * of text. The label and secondary label should be consistently aligned. With localisation and/or
213 * large font sizes, the [Chip] height adjusts to accommodate the contents.
214 *
215 * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
216 * the text starts next to the icon.
217 *
218 * The [Chip] can have different styles with configurable content colors, background colors
219 * including gradients, these are provided by [ChipColors] implementations.
220 *
221 * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
222 * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
223 * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
224 *
225 * Chips can be enabled or disabled. A disabled chip will not respond to click events.
226 *
227 * Example of a [Chip] with icon and a label only with longer text:
228 *
229 * @sample androidx.wear.compose.material.samples.ChipWithIconAndLabel
230 *
231 * Example of a [Chip] with icon, label and secondary label:
232 *
233 * @sample androidx.wear.compose.material.samples.ChipWithIconAndLabels
234 *
235 * For more information, see the
236 * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
237 *
238 * @param label A slot for providing the chip's main label. The contents are expected to be text
239 * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
240 * @param onClick Will be called when the user clicks the chip
241 * @param modifier Modifier to be applied to the chip
242 * @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
243 * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned
244 * if not. label and secondaryLabel contents should be consistently aligned.
245 * @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
246 * and vertically aligned icon of size [ChipDefaults.IconSize] or [ChipDefaults.LargeIconSize]. In
247 * order to correctly render when the Chip is not enabled the icon must set its alpha value to
248 * [LocalContentAlpha].
249 * @param colors [ChipColors] that will be used to resolve the background and content color for this
250 * chip in different states. See [ChipDefaults.chipColors]. Defaults to
251 * [ChipDefaults.primaryChipColors]
252 * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
253 * clickable
254 * @param interactionSource The [MutableInteractionSource] representing the stream of [Interaction]s
255 * for this Chip. You can create and pass in your own remembered [MutableInteractionSource] if you
256 * want to observe [Interaction]s and customize the appearance / behavior of this Chip in
257 * different [Interaction]s.
258 * @param contentPadding The spacing values to apply internally between the container and the
259 * content
260 */
261 @Deprecated(
262 "This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
263 "A newer overload is available with an additional shape parameter.",
264 level = DeprecationLevel.HIDDEN
265 )
266 @Composable
Chipnull267 public fun Chip(
268 label: @Composable RowScope.() -> Unit,
269 onClick: () -> Unit,
270 modifier: Modifier = Modifier,
271 secondaryLabel: (@Composable RowScope.() -> Unit)? = null,
272 icon: (@Composable BoxScope.() -> Unit)? = null,
273 colors: ChipColors = ChipDefaults.primaryChipColors(),
274 enabled: Boolean = true,
275 interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
276 contentPadding: PaddingValues = ChipDefaults.ContentPadding,
277 ): Unit =
278 Chip(
279 label,
280 onClick,
281 modifier,
282 secondaryLabel,
283 icon,
284 colors,
285 enabled,
286 interactionSource,
287 contentPadding,
288 MaterialTheme.shapes.small
289 )
290
291 /**
292 * Wear Material [Chip] that offers three slots and a specific layout for an icon, label and
293 * secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with the icon,
294 * if provided, at the start of a row, with a column next containing the two label slots.
295 *
296 * The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
297 * of [Typography.button] style. If no secondary label is provided then the label can be two lines
298 * of text. The label and secondary label should be consistently aligned. With localisation and/or
299 * large font sizes, the [Chip] height adjusts to accommodate the contents.
300 *
301 * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
302 * the text starts next to the icon.
303 *
304 * The [Chip] can have different styles with configurable content colors, background colors
305 * including gradients, these are provided by [ChipColors] implementations.
306 *
307 * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
308 * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
309 * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
310 *
311 * Chips can be enabled or disabled. A disabled chip will not respond to click events.
312 *
313 * Example of a [Chip] with icon and a label only with longer text:
314 *
315 * @sample androidx.wear.compose.material.samples.ChipWithIconAndLabel
316 *
317 * Example of a [Chip] with icon, label and secondary label:
318 *
319 * @sample androidx.wear.compose.material.samples.ChipWithIconAndLabels
320 *
321 * For more information, see the
322 * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
323 *
324 * @param label A slot for providing the chip's main label. The contents are expected to be text
325 * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
326 * @param onClick Will be called when the user clicks the chip
327 * @param modifier Modifier to be applied to the chip
328 * @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
329 * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned
330 * if not. label and secondaryLabel contents should be consistently aligned.
331 * @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
332 * and vertically aligned icon of size [ChipDefaults.IconSize] or [ChipDefaults.LargeIconSize]. In
333 * order to correctly render when the Chip is not enabled the icon must set its alpha value to
334 * [LocalContentAlpha].
335 * @param colors [ChipColors] that will be used to resolve the background and content color for this
336 * chip in different states. See [ChipDefaults.chipColors]. Defaults to
337 * [ChipDefaults.primaryChipColors]
338 * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
339 * clickable
340 * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
341 * emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
342 * preview the chip in different states. Note that if `null` is provided, interactions will still
343 * happen internally.
344 * @param contentPadding The spacing values to apply internally between the container and the
345 * content
346 * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
347 * shape is a key characteristic of the Wear Material Theme
348 * @param border [ChipBorder] that will be used to resolve the chip border in different states. See
349 * [ChipDefaults.chipBorder].
350 */
351 @Composable
Chipnull352 public fun Chip(
353 label: @Composable RowScope.() -> Unit,
354 onClick: () -> Unit,
355 modifier: Modifier = Modifier,
356 secondaryLabel: (@Composable RowScope.() -> Unit)? = null,
357 icon: (@Composable BoxScope.() -> Unit)? = null,
358 colors: ChipColors = ChipDefaults.primaryChipColors(),
359 enabled: Boolean = true,
360 interactionSource: MutableInteractionSource? = null,
361 contentPadding: PaddingValues = ChipDefaults.ContentPadding,
362 shape: Shape = MaterialTheme.shapes.large,
363 border: ChipBorder = ChipDefaults.chipBorder()
364 ) {
365 ChipImpl(
366 onClick = onClick,
367 label = label,
368 labelTypography = MaterialTheme.typography.button,
369 modifier = modifier.chipSizeModifier(),
370 secondaryLabel = secondaryLabel,
371 icon = icon,
372 colors = colors,
373 enabled = enabled,
374 interactionSource = interactionSource,
375 contentPadding = contentPadding,
376 shape = shape,
377 border = border,
378 defaultIconSpacing = ChipDefaults.IconSpacing
379 )
380 }
381
382 /**
383 * Wear Material [OutlinedChip] that offers three slots and a specific layout for an icon, label and
384 * secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with the icon,
385 * if provided, at the start of a row, with a column next containing the two label slots.
386 *
387 * The [OutlinedChip] is Stadium shaped and has a max height designed to take no more than two lines
388 * of text of [Typography.button] style. If no secondary label is provided then the label can be two
389 * lines of text. The label and secondary label should be consistently aligned. With localisation
390 * and/or large font sizes, the [OutlinedChip] height adjusts to accommodate the contents.
391 *
392 * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
393 * the text starts next to the icon.
394 *
395 * the [OutlinedChip] has a transparent background, a thin border and contents which are colored
396 * with the theme primary color. Colors can be obtained and customized using
397 * [ChipDefaults.outlinedChipColors()].
398 *
399 * Chips can be enabled or disabled. A disabled chip will not respond to click events.
400 *
401 * Example of a [OutlinedChip] with icon and a label only with longer text:
402 *
403 * @sample androidx.wear.compose.material.samples.OutlinedChipWithIconAndLabel
404 *
405 * For more information, see the
406 * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
407 *
408 * @param label A slot for providing the chip's main label. The contents are expected to be text
409 * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
410 * @param onClick Will be called when the user clicks the chip
411 * @param modifier Modifier to be applied to the chip
412 * @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
413 * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned
414 * if not. label and secondaryLabel contents should be consistently aligned.
415 * @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
416 * and vertically aligned icon of size [ChipDefaults.IconSize] or [ChipDefaults.LargeIconSize]. In
417 * order to correctly render when the Chip is not enabled the icon must set its alpha value to
418 * [LocalContentAlpha].
419 * @param colors [ChipColors] that will be used to resolve the background and content color for this
420 * chip in different states.
421 * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
422 * clickable
423 * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
424 * emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
425 * preview the chip in different states. Note that if `null` is provided, interactions will still
426 * happen internally.
427 * @param contentPadding The spacing values to apply internally between the container and the
428 * content
429 * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
430 * shape is a key characteristic of the Wear Material Theme
431 * @param border [ChipBorder] that will be used to resolve the chip border in different states.
432 */
433 @Composable
OutlinedChipnull434 public fun OutlinedChip(
435 label: @Composable RowScope.() -> Unit,
436 onClick: () -> Unit,
437 modifier: Modifier = Modifier,
438 secondaryLabel: (@Composable RowScope.() -> Unit)? = null,
439 icon: (@Composable BoxScope.() -> Unit)? = null,
440 colors: ChipColors = ChipDefaults.outlinedChipColors(),
441 enabled: Boolean = true,
442 interactionSource: MutableInteractionSource? = null,
443 contentPadding: PaddingValues = ChipDefaults.ContentPadding,
444 shape: Shape = MaterialTheme.shapes.large,
445 border: ChipBorder = ChipDefaults.outlinedChipBorder()
446 ): Unit =
447 Chip(
448 label = label,
449 onClick = onClick,
450 modifier = modifier,
451 secondaryLabel = secondaryLabel,
452 icon = icon,
453 colors = colors,
454 enabled = enabled,
455 interactionSource = interactionSource,
456 contentPadding = contentPadding,
457 shape = shape,
458 border = border
459 )
460
461 /**
462 * A compact Wear Material Chip that offers two slots and a specific layout for an icon and label.
463 * Both the icon and label are optional however it is expected that at least one will be provided.
464 *
465 * The [CompactChip] is Stadium shaped and has a max height designed to take no more than one line
466 * of text of [Typography.caption1] style and/or one icon. The default max height is
467 * [ChipDefaults.CompactChipHeight]. This includes a visible chip height of 32.dp and 8.dp of
468 * padding above and below the chip in order to meet accessibility guidelines that request a minimum
469 * of 48.dp height and width of tappable area.
470 *
471 * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
472 * the text starts next to the icon.
473 *
474 * The items are laid out as follows.
475 * 1. If a label is provided then the chip will be laid out with the optional icon at the start of a
476 * row followed by the label with a default max height of [ChipDefaults.CompactChipHeight].
477 * 2. If only an icon is provided it will be laid out vertically and horizontally centered with a
478 * default height of [ChipDefaults.CompactChipHeight] and the default width of
479 * [ChipDefaults.IconOnlyCompactChipWidth]
480 *
481 * If neither icon nor label is provided then the chip will displayed like an icon only chip but
482 * with no contents and [ChipColors.background()] color.
483 *
484 * The [CompactChip] can have different styles with configurable content colors, background colors
485 * including gradients, these are provided by [ChipColors] implementations.
486 *
487 * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
488 * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
489 * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
490 *
491 * Chips can be enabled or disabled. A disabled chip will not respond to click events.
492 *
493 * Example of a [CompactChip] with icon and single line of label text:
494 *
495 * @sample androidx.wear.compose.material.samples.CompactChipWithIconAndLabel
496 *
497 * Example of a [CompactChip] with a label, note that the text is center aligned:
498 *
499 * @sample androidx.wear.compose.material.samples.CompactChipWithLabel
500 *
501 * Example of a [CompactChip] with an icon only, note that the recommended icon size is 24x24 when
502 * only an icon is displayed:
503 *
504 * @sample androidx.wear.compose.material.samples.CompactChipWithIcon
505 *
506 * For more information, see the
507 * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
508 *
509 * @param onClick Will be called when the user clicks the chip
510 * @param modifier Modifier to be applied to the chip
511 * @param label A slot for providing the chip's main label. The contents are expected to be text
512 * which is "start" aligned if there is an icon preset and "center" aligned if not.
513 * @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
514 * and vertically aligned icon of size [ChipDefaults.SmallIconSize] when used with a label or
515 * [ChipDefaults.IconSize] when used as the only content in the CompactChip. In order to correctly
516 * render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
517 * @param colors [ChipColors] that will be used to resolve the background and content color for this
518 * chip in different states. See [ChipDefaults.chipColors]. Defaults to
519 * [ChipDefaults.primaryChipColors]
520 * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
521 * clickable
522 * @param interactionSource The [MutableInteractionSource] representing the stream of [Interaction]s
523 * for this Chip. You can create and pass in your own remembered [MutableInteractionSource] if you
524 * want to observe [Interaction]s and customize the appearance / behavior of this Chip in
525 * different [Interaction]s.
526 * @param contentPadding The spacing values to apply internally between the container and the
527 * content
528 */
529 @Deprecated(
530 "This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
531 "A newer overload is available with an additional shape parameter.",
532 level = DeprecationLevel.HIDDEN
533 )
534 @Composable
535 public fun CompactChip(
536 onClick: () -> Unit,
537 modifier: Modifier = Modifier,
538 label: (@Composable RowScope.() -> Unit)? = null,
539 icon: (@Composable BoxScope.() -> Unit)? = null,
540 colors: ChipColors = ChipDefaults.primaryChipColors(),
541 enabled: Boolean = true,
542 interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
543 contentPadding: PaddingValues = ChipDefaults.CompactChipContentPadding,
544 ): Unit =
545 CompactChip(
546 onClick,
547 modifier,
548 label,
549 icon,
550 colors,
551 enabled,
552 interactionSource,
553 contentPadding,
554 MaterialTheme.shapes.small,
555 ChipDefaults.chipBorder()
556 )
557
558 /**
559 * A compact Wear Material Chip that offers two slots and a specific layout for an icon and label.
560 * Both the icon and label are optional however it is expected that at least one will be provided.
561 *
562 * The [CompactChip] is Stadium shaped and has a max height designed to take no more than one line
563 * of text of [Typography.caption1] style and/or one icon. The default max height is
564 * [ChipDefaults.CompactChipHeight]. This includes a visible chip height of 32.dp and 8.dp of
565 * padding above and below the chip in order to meet accessibility guidelines that request a minimum
566 * of 48.dp height and width of tappable area.
567 *
568 * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
569 * the text starts next to the icon.
570 *
571 * The items are laid out as follows.
572 * 1. If a label is provided then the chip will be laid out with the optional icon at the start of a
573 * row followed by the label with a default max height of [ChipDefaults.CompactChipHeight].
574 * 2. If only an icon is provided it will be laid out vertically and horizontally centered with a
575 * default height of [ChipDefaults.CompactChipHeight] and the default width of
576 * [ChipDefaults.IconOnlyCompactChipWidth]
577 *
578 * If neither icon nor label is provided then the chip will displayed like an icon only chip but
579 * with no contents and [ChipColors.background()] color.
580 *
581 * The [CompactChip] can have different styles with configurable content colors, background colors
582 * including gradients, these are provided by [ChipColors] implementations.
583 *
584 * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
585 * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
586 * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
587 *
588 * Chips can be enabled or disabled. A disabled chip will not respond to click events.
589 *
590 * Example of a [CompactChip] with icon and single line of label text:
591 *
592 * @sample androidx.wear.compose.material.samples.CompactChipWithIconAndLabel
593 *
594 * Example of a [CompactChip] with a label, note that the text is center aligned:
595 *
596 * @sample androidx.wear.compose.material.samples.CompactChipWithLabel
597 *
598 * Example of a [CompactChip] with an icon only, note that the recommended icon size is 24x24 when
599 * only an icon is displayed:
600 *
601 * @sample androidx.wear.compose.material.samples.CompactChipWithIcon
602 *
603 * For more information, see the
604 * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
605 *
606 * @param onClick Will be called when the user clicks the chip
607 * @param modifier Modifier to be applied to the chip
608 * @param label A slot for providing the chip's main label. The contents are expected to be text
609 * which is "start" aligned if there is an icon preset and "center" aligned if not.
610 * @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
611 * and vertically aligned icon of size [ChipDefaults.SmallIconSize] when used with a label or
612 * [ChipDefaults.IconSize] when used as the only content in the CompactChip. In order to correctly
613 * render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
614 * @param colors [ChipColors] that will be used to resolve the background and content color for this
615 * chip in different states. See [ChipDefaults.chipColors]. Defaults to
616 * [ChipDefaults.primaryChipColors]
617 * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
618 * clickable
619 * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
620 * emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
621 * preview the chip in different states. Note that if `null` is provided, interactions will still
622 * happen internally.
623 * @param contentPadding The spacing values to apply internally between the container and the
624 * content
625 * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
626 * shape is a key characteristic of the Wear Material Theme
627 * @param border [ChipBorder] that will be used to resolve the border for this chip in different
628 * states. See [ChipDefaults.chipBorder].
629 */
630 @Composable
CompactChipnull631 public fun CompactChip(
632 onClick: () -> Unit,
633 modifier: Modifier = Modifier,
634 label: (@Composable RowScope.() -> Unit)? = null,
635 icon: (@Composable BoxScope.() -> Unit)? = null,
636 colors: ChipColors = ChipDefaults.primaryChipColors(),
637 enabled: Boolean = true,
638 interactionSource: MutableInteractionSource? = null,
639 contentPadding: PaddingValues = ChipDefaults.CompactChipContentPadding,
640 shape: Shape = MaterialTheme.shapes.large,
641 border: ChipBorder = ChipDefaults.chipBorder()
642 ) {
643 if (label != null) {
644 ChipImpl(
645 modifier =
646 modifier.compactChipModifier().padding(ChipDefaults.CompactChipTapTargetPadding),
647 label = label,
648 labelTypography = MaterialTheme.typography.caption1,
649 onClick = onClick,
650 colors = colors,
651 secondaryLabel = null,
652 icon = icon,
653 enabled = enabled,
654 interactionSource = interactionSource,
655 contentPadding = contentPadding,
656 shape = shape,
657 border = border,
658 defaultIconSpacing = ChipDefaults.IconSpacing,
659 )
660 } else {
661 // Icon only compact chips have their own layout with a specific width and center aligned
662 // content. We use the base simple single slot Chip under the covers.
663 ChipImpl(
664 modifier =
665 modifier
666 .compactChipModifier()
667 .width(ChipDefaults.IconOnlyCompactChipWidth)
668 .padding(ChipDefaults.CompactChipTapTargetPadding),
669 onClick = onClick,
670 colors = colors,
671 border = border,
672 enabled = enabled,
673 contentPadding = contentPadding,
674 shape = shape,
675 interactionSource = interactionSource,
676 ) {
677 // Use a box to fill and center align the icon into the single slot of the Chip
678 Box(modifier = Modifier.fillMaxSize().wrapContentSize(align = Alignment.Center)) {
679 if (icon != null) {
680 icon()
681 }
682 }
683 }
684 }
685 }
686
687 /**
688 * A compact Outlined Wear Material Chip that offers two slots and a specific layout for an icon and
689 * label. Both the icon and label are optional however it is expected that at least one will be
690 * provided.
691 *
692 * The [CompactChip] is Stadium shaped and has a max height designed to take no more than one line
693 * of text of [Typography.caption1] style and/or one icon. The default max height is
694 * [ChipDefaults.CompactChipHeight]. This includes a visible chip height of 32.dp and 8.dp of
695 * padding above and below the chip in order to meet accessibility guidelines that request a minimum
696 * of 48.dp height and width of tappable area.
697 *
698 * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
699 * the text starts next to the icon.
700 *
701 * The items are laid out as follows.
702 * 1. If a label is provided then the chip will be laid out with the optional icon at the start of a
703 * row followed by the label with a default max height of [ChipDefaults.CompactChipHeight].
704 * 2. If only an icon is provided it will be laid out vertically and horizontally centered with a
705 * default height of [ChipDefaults.CompactChipHeight] and the default width of
706 * [ChipDefaults.IconOnlyCompactChipWidth]
707 *
708 * If neither icon nor label is provided then the chip will displayed like an icon only chip but
709 * with no contents and [ChipColors.background()] color.
710 *
711 * the [OutlinedCompactChip] has a transparent background, a thin border and contents which are
712 * colored with the theme primary color. Colors can be obtained and customized using
713 * [ChipDefaults.outlinedChipColors()].
714 *
715 * Chips can be enabled or disabled. A disabled chip will not respond to click events.
716 *
717 * Example of a [OutlinedCompactChip] with icon and single line of label text:
718 *
719 * @sample androidx.wear.compose.material.samples.OutlinedCompactChipWithIconAndLabel
720 *
721 * For more information, see the
722 * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
723 *
724 * @param onClick Will be called when the user clicks the chip
725 * @param modifier Modifier to be applied to the chip
726 * @param label A slot for providing the chip's main label. The contents are expected to be text
727 * which is "start" aligned if there is an icon preset and "center" aligned if not.
728 * @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
729 * and vertically aligned icon of size [ChipDefaults.SmallIconSize] when used with a label or
730 * [ChipDefaults.IconSize] when used as the only content in the CompactChip. In order to correctly
731 * render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
732 * @param colors [ChipColors] that will be used to resolve the background and content color for this
733 * chip in different states. See [ChipDefaults.outlinedChipColors]. Defaults to
734 * [ChipDefaults.primaryChipColors]
735 * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
736 * clickable
737 * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
738 * emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
739 * preview the chip in different states. Note that if `null` is provided, interactions will still
740 * happen internally.
741 * @param contentPadding The spacing values to apply internally between the container and the
742 * content
743 * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
744 * shape is a key characteristic of the Wear Material Theme
745 * @param border [ChipBorder] that will be used to resolve the border for this chip in different
746 * states. See [ChipDefaults.outlinedChipBorder].
747 */
748 @Composable
OutlinedCompactChipnull749 public fun OutlinedCompactChip(
750 onClick: () -> Unit,
751 modifier: Modifier = Modifier,
752 label: (@Composable RowScope.() -> Unit)? = null,
753 icon: (@Composable BoxScope.() -> Unit)? = null,
754 colors: ChipColors = ChipDefaults.outlinedChipColors(),
755 enabled: Boolean = true,
756 interactionSource: MutableInteractionSource? = null,
757 contentPadding: PaddingValues = ChipDefaults.CompactChipContentPadding,
758 shape: Shape = MaterialTheme.shapes.large,
759 border: ChipBorder = ChipDefaults.outlinedChipBorder()
760 ): Unit =
761 CompactChip(
762 onClick = onClick,
763 modifier = modifier,
764 label = label,
765 icon = icon,
766 colors = colors,
767 enabled = enabled,
768 interactionSource = interactionSource,
769 contentPadding = contentPadding,
770 shape = shape,
771 border = border
772 )
773
774 /**
775 * Represents the background and content colors used in a chip in different states.
776 *
777 * See [ChipDefaults.primaryChipColors] for the default colors used in a primary styled [Chip]. See
778 * [ChipDefaults.secondaryChipColors] for the default colors used in a secondary styled [Chip].
779 */
780 @Stable
781 public interface ChipColors {
782 /**
783 * Represents the background treatment for this chip, depending on [enabled]. Backgrounds can be
784 * solid, transparent or have a gradient applied.
785 *
786 * @param enabled Whether the chip is enabled
787 */
788 @Composable public fun background(enabled: Boolean): State<Painter>
789
790 /**
791 * Represents the content color for this chip, depending on [enabled].
792 *
793 * @param enabled Whether the chip is enabled
794 */
795 @Composable public fun contentColor(enabled: Boolean): State<Color>
796
797 /**
798 * Represents the secondary content color for this chip, depending on [enabled].
799 *
800 * @param enabled Whether the chip is enabled
801 */
802 @Composable public fun secondaryContentColor(enabled: Boolean): State<Color>
803
804 /**
805 * Represents the icon color for this chip, depending on [enabled].
806 *
807 * @param enabled Whether the chip is enabled
808 */
809 @Composable public fun iconColor(enabled: Boolean): State<Color>
810 }
811
812 /** Represents the border stroke used in a [Chip] in different states. */
813 @Stable
814 public interface ChipBorder {
815 @Composable
816 /**
817 * Represents the border stroke for this chip, depending on [enabled] or null if no border
818 *
819 * @param enabled Whether the chip is enabled
820 */
borderStrokenull821 public fun borderStroke(enabled: Boolean): State<BorderStroke?>
822 }
823
824 /** Contains the default values used by [Chip] */
825 public object ChipDefaults {
826
827 /**
828 * Creates a [ChipColors] that represents the default background and content colors for a
829 * primary [Chip]. Primary chips have a colored background with a contrasting content color. If
830 * a chip is disabled then the colors will have an alpha([ContentAlpha.disabled]) value applied.
831 *
832 * @param backgroundColor The background color of this [Chip] when enabled
833 * @param contentColor The content color of this [Chip] when enabled
834 * @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
835 * for secondaryLabel content
836 * @param iconColor The icon color of this [Chip] when enabled, used for icon content
837 */
838 @Composable
839 public fun primaryChipColors(
840 backgroundColor: Color = MaterialTheme.colors.primary,
841 contentColor: Color = contentColorFor(backgroundColor),
842 secondaryContentColor: Color = contentColor,
843 iconColor: Color = contentColor
844 ): ChipColors {
845 // For light background colors, the default disabled content colors do not provide
846 // sufficient contrast. Instead, we default to using background for disabled content.
847 // See b/254025377
848 return chipColors(
849 backgroundColor = backgroundColor,
850 contentColor = contentColor,
851 secondaryContentColor = secondaryContentColor,
852 iconColor = iconColor,
853 disabledContentColor = MaterialTheme.colors.background,
854 disabledSecondaryContentColor = MaterialTheme.colors.background,
855 disabledIconColor = MaterialTheme.colors.background,
856 )
857 }
858
859 /**
860 * Creates a [ChipColors] that represents the background and content colors for a primary [Chip]
861 * with a linear gradient for a background. The gradient will be between startBackgroundColor
862 * and endBackgroundColor. Gradient backgrounds are typically used for chips showing an on-going
863 * activity, such as a music track that is playing.
864 *
865 * Gradient background chips should have a content color that contrasts with the background
866 * gradient. If a chip is disabled then the colors will have an alpha([ContentAlpha.disabled])
867 * value applied.
868 *
869 * @param startBackgroundColor The background color used at the start of the gradient of this
870 * [Chip] when enabled
871 * @param endBackgroundColor The background color used at the end of the gradient of this [Chip]
872 * when enabled
873 * @param contentColor The content color of this [Chip] when enabled
874 * @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
875 * for secondaryLabel content
876 * @param iconColor The icon color of this [Chip] when enabled, used for icon content
877 * @param gradientDirection Whether the chips gradient should be start to end (indicated by
878 * [LayoutDirection.Ltr]) or end to start (indicated by [LayoutDirection.Rtl]).
879 */
880 @Composable
881 public fun gradientBackgroundChipColors(
882 startBackgroundColor: Color =
883 MaterialTheme.colors.primary
884 .copy(alpha = 0.5f)
885 .compositeOver(MaterialTheme.colors.surface),
886 endBackgroundColor: Color =
887 MaterialTheme.colors.surface
888 .copy(alpha = 0f)
889 .compositeOver(MaterialTheme.colors.surface),
890 contentColor: Color = contentColorFor(endBackgroundColor),
891 secondaryContentColor: Color = contentColor,
892 iconColor: Color = contentColor,
893 gradientDirection: LayoutDirection = LocalLayoutDirection.current
894 ): ChipColors {
895 val backgroundColors: List<Color>
896 val disabledBackgroundColors: List<Color>
897 if (gradientDirection == LayoutDirection.Ltr) {
898 backgroundColors = listOf(startBackgroundColor, endBackgroundColor)
899 disabledBackgroundColors =
900 listOf(
901 startBackgroundColor.copy(alpha = ContentAlpha.disabled),
902 endBackgroundColor.copy(alpha = ContentAlpha.disabled)
903 )
904 } else {
905 backgroundColors = listOf(endBackgroundColor, startBackgroundColor)
906 disabledBackgroundColors =
907 listOf(
908 endBackgroundColor.copy(alpha = ContentAlpha.disabled),
909 startBackgroundColor.copy(alpha = ContentAlpha.disabled),
910 )
911 }
912 return DefaultChipColors(
913 backgroundPainter = BrushPainter(Brush.linearGradient(backgroundColors)),
914 contentColor = contentColor,
915 secondaryContentColor = secondaryContentColor,
916 iconColor = iconColor,
917 disabledBackgroundPainter =
918 BrushPainter(Brush.linearGradient(disabledBackgroundColors)),
919 disabledContentColor = contentColor.copy(alpha = ContentAlpha.disabled),
920 disabledSecondaryContentColor =
921 secondaryContentColor.copy(alpha = ContentAlpha.disabled),
922 disabledIconColor = iconColor.copy(alpha = ContentAlpha.disabled),
923 )
924 }
925
926 /**
927 * Creates a [ChipColors] that represents the default background and content colors for a
928 * secondary [Chip]. Secondary chips have a muted background with a contrasting content color.
929 * If a chip is disabled then the colors will have an alpha([ContentAlpha.disabled]) value
930 * applied.
931 *
932 * @param backgroundColor The background color of this [Chip] when enabled
933 * @param contentColor The content color of this [Chip] when enabled
934 * @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
935 * for secondaryLabel content
936 * @param iconColor The icon color of this [Chip] when enabled, used for icon content
937 */
938 @Composable
939 public fun secondaryChipColors(
940 backgroundColor: Color = MaterialTheme.colors.surface,
941 contentColor: Color = contentColorFor(backgroundColor),
942 secondaryContentColor: Color = contentColor,
943 iconColor: Color = contentColor
944 ): ChipColors {
945 return chipColors(
946 backgroundColor = backgroundColor,
947 contentColor = contentColor,
948 secondaryContentColor = secondaryContentColor,
949 iconColor = iconColor
950 )
951 }
952
953 /**
954 * Creates a [ChipColors] that represents the default background (transparent) and content
955 * colors for a child [Chip]. Child chips have a transparent background and use a default
956 * content color of [Colors.onSurface].
957 *
958 * If a chip is disabled then the colors will have an alpha([ContentAlpha.disabled]) value
959 * applied.
960 *
961 * @param contentColor The content color of this [Chip] when enabled
962 * @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
963 * for secondaryLabel content
964 * @param iconColor The icon color of this [Chip] when enabled, used for icon content
965 */
966 @Composable
967 public fun childChipColors(
968 contentColor: Color = MaterialTheme.colors.onSurface,
969 secondaryContentColor: Color = contentColor,
970 iconColor: Color = contentColor
971 ): ChipColors {
972 return chipColors(
973 backgroundColor = Color.Transparent,
974 contentColor = contentColor,
975 secondaryContentColor = secondaryContentColor,
976 iconColor = iconColor,
977 disabledBackgroundColor = Color.Transparent
978 )
979 }
980
981 /**
982 * Creates a [ChipColors] for an image background [Chip]. Image background chips have an image
983 * as the background of the chip typically with a scrim over the image to ensure that the
984 * content is visible, and use a default content color of [Colors.onBackground].
985 *
986 * @param backgroundImagePainter The [Painter] to use to draw the background of the [Chip]
987 * @param backgroundImageScrimBrush The [Brush] to use to paint a scrim over the background
988 * image to ensure that any text drawn over the image is legible
989 * @param contentColor The content color of this [Chip] when enabled
990 * @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
991 * for secondaryLabel content
992 * @param iconColor The icon color of this [Chip] when enabled, used for icon content
993 */
994 @Composable
995 public fun imageBackgroundChipColors(
996 backgroundImagePainter: Painter,
997 backgroundImageScrimBrush: Brush =
998 Brush.linearGradient(
999 colors =
1000 listOf(
1001 MaterialTheme.colors.surface.copy(alpha = 1.0f),
1002 MaterialTheme.colors.surface.copy(alpha = 0f)
1003 )
1004 ),
1005 contentColor: Color = MaterialTheme.colors.onBackground,
1006 secondaryContentColor: Color = contentColor,
1007 iconColor: Color = contentColor,
1008 ): ChipColors {
1009 val backgroundPainter =
1010 remember(backgroundImagePainter, backgroundImageScrimBrush) {
1011 ImageWithScrimPainter(
1012 imagePainter = backgroundImagePainter,
1013 brush = backgroundImageScrimBrush
1014 )
1015 }
1016
1017 val disabledContentAlpha = ContentAlpha.disabled
1018 val disabledBackgroundPainter =
1019 remember(backgroundImagePainter, backgroundImageScrimBrush, disabledContentAlpha) {
1020 ImageWithScrimPainter(
1021 imagePainter = backgroundImagePainter,
1022 brush = backgroundImageScrimBrush,
1023 alpha = disabledContentAlpha,
1024 )
1025 }
1026 return DefaultChipColors(
1027 backgroundPainter = backgroundPainter,
1028 contentColor = contentColor,
1029 secondaryContentColor = secondaryContentColor,
1030 iconColor = iconColor,
1031 disabledBackgroundPainter = disabledBackgroundPainter,
1032 disabledContentColor = contentColor.copy(alpha = ContentAlpha.disabled),
1033 disabledSecondaryContentColor =
1034 secondaryContentColor.copy(alpha = ContentAlpha.disabled),
1035 disabledIconColor = iconColor.copy(alpha = ContentAlpha.disabled),
1036 )
1037 }
1038
1039 /**
1040 * Creates a [ChipColors] for an outline [Chip]. Outline chips have a transparent background
1041 * with a thin border.
1042 *
1043 * If a chip is disabled then the colors will have an alpha([ContentAlpha.disabled]) value
1044 * applied.
1045 *
1046 * @param contentColor The content color of this [Chip] when enabled
1047 * @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
1048 * for secondaryLabel content
1049 * @param iconColor The icon color of this [Chip] when enabled, used for icon content
1050 */
1051 @Composable
1052 public fun outlinedChipColors(
1053 contentColor: Color = MaterialTheme.colors.primary,
1054 secondaryContentColor: Color = contentColor,
1055 iconColor: Color = contentColor,
1056 ): ChipColors {
1057 return chipColors(
1058 backgroundColor = Color.Transparent,
1059 contentColor = contentColor,
1060 secondaryContentColor = secondaryContentColor,
1061 iconColor = iconColor,
1062 disabledBackgroundColor = Color.Transparent,
1063 )
1064 }
1065
1066 /**
1067 * Creates a default (no border) [ChipBorder] for a [Chip]
1068 *
1069 * @param borderStroke The border for this [Chip] when enabled
1070 * @param disabledBorderStroke The border to use for this [Chip] when disabled
1071 */
1072 @Composable
1073 public fun chipBorder(
1074 borderStroke: BorderStroke? = null,
1075 disabledBorderStroke: BorderStroke? = null
1076 ): ChipBorder {
1077 return DefaultChipBorder(
1078 borderStroke = borderStroke,
1079 disabledBorderStroke = disabledBorderStroke
1080 )
1081 }
1082
1083 /**
1084 * Creates a [ChipBorder] for an [OutlinedChip]
1085 *
1086 * @param borderColor The color to use for the border for this [OutlinedChip] when enabled
1087 * @param disabledBorderColor The color to use for the border for this [OutlinedChip] when
1088 * disabled
1089 * @param borderWidth The width to use for the border for this [OutlinedChip]
1090 */
1091 @Composable
1092 public fun outlinedChipBorder(
1093 borderColor: Color = MaterialTheme.colors.primaryVariant.copy(alpha = 0.6f),
1094 disabledBorderColor: Color = borderColor.copy(alpha = ContentAlpha.disabled),
1095 borderWidth: Dp = 1.dp
1096 ): ChipBorder {
1097 return DefaultChipBorder(
1098 borderStroke = BorderStroke(borderWidth, borderColor),
1099 disabledBorderStroke = BorderStroke(borderWidth, disabledBorderColor)
1100 )
1101 }
1102
1103 public val ChipHorizontalPadding: Dp = 14.dp
1104 public val ChipVerticalPadding: Dp = 6.dp
1105
1106 /** The default content padding used by [Chip] */
1107 public val ContentPadding: PaddingValues =
1108 PaddingValues(
1109 start = ChipHorizontalPadding,
1110 top = ChipVerticalPadding,
1111 end = ChipHorizontalPadding,
1112 bottom = ChipVerticalPadding
1113 )
1114
1115 public val CompactChipHorizontalPadding: Dp = 12.dp
1116 public val CompactChipVerticalPadding: Dp = 0.dp
1117
1118 /** The default content padding used by [CompactChip] */
1119 public val CompactChipContentPadding: PaddingValues =
1120 PaddingValues(
1121 start = CompactChipHorizontalPadding,
1122 top = CompactChipVerticalPadding,
1123 end = CompactChipHorizontalPadding,
1124 bottom = CompactChipVerticalPadding
1125 )
1126
1127 /**
1128 * The default height applied for the [Chip]. Note that you can override it by applying
1129 * Modifier.heightIn directly on [Chip].
1130 */
1131 public val Height: Dp = 52.dp
1132
1133 /**
1134 * The height applied for the [CompactChip]. This includes a visible chip height of 32.dp and
1135 * 8.dp of padding above and below the chip in order to meet accessibility guidelines that
1136 * request a minimum of 48.dp height and width of tappable area.
1137 *
1138 * Note that you can override it by adjusting Modifier.height and Modifier.padding directly on
1139 * [CompactChip].
1140 */
1141 public val CompactChipHeight: Dp = 48.dp
1142
1143 /**
1144 * The default padding to be provided around a [CompactChip] in order to ensure that its
1145 * tappable area meets minimum UX guidance.
1146 */
1147 public val CompactChipTapTargetPadding: PaddingValues = PaddingValues(top = 8.dp, bottom = 8.dp)
1148
1149 /**
1150 * The default width applied for the [CompactChip] when it has no label provided. Note that you
1151 * can override it by applying Modifier.width directly on [CompactChip].
1152 */
1153 internal val IconOnlyCompactChipWidth = 52.dp
1154
1155 /** The default size of the icon when used inside a [Chip]. */
1156 public val IconSize: Dp = 24.dp
1157
1158 /** The size of the icon when used inside a Large "Avatar" [Chip]. */
1159 public val LargeIconSize: Dp = 32.dp
1160
1161 /** The size of the icon when used inside a "Compact" [Chip]. */
1162 public val SmallIconSize: Dp = 20.dp
1163
1164 /**
1165 * The default size of the spacing between an icon and a text when they are used inside a
1166 * [Chip].
1167 */
1168 internal val IconSpacing = 6.dp
1169
1170 /**
1171 * Creates a [ChipColors] that represents the default background and content colors used in a
1172 * [Chip].
1173 *
1174 * @param backgroundColor The background color of this [Chip] when enabled
1175 * @param contentColor The content color of this [Chip] when enabled
1176 * @param secondaryContentColor The content color of this [Chip] when enabled
1177 * @param iconColor The content color of this [Chip] when enabled
1178 * @param disabledBackgroundColor The background color of this [Chip] when not enabled
1179 * @param disabledContentColor The content color of this [Chip] when not enabled
1180 * @param disabledSecondaryContentColor The content color of this [Chip] when not enabled
1181 * @param disabledIconColor The content color of this [Chip] when not enabled
1182 */
1183 @Composable
1184 public fun chipColors(
1185 backgroundColor: Color = MaterialTheme.colors.primary,
1186 contentColor: Color = contentColorFor(backgroundColor),
1187 secondaryContentColor: Color = contentColor,
1188 iconColor: Color = contentColor,
1189 disabledBackgroundColor: Color = backgroundColor.copy(alpha = ContentAlpha.disabled),
1190 disabledContentColor: Color = contentColor.copy(alpha = ContentAlpha.disabled),
1191 disabledSecondaryContentColor: Color =
1192 secondaryContentColor.copy(alpha = ContentAlpha.disabled),
1193 disabledIconColor: Color = iconColor.copy(alpha = ContentAlpha.disabled),
1194 ): ChipColors =
1195 DefaultChipColors(
1196 backgroundColor = backgroundColor,
1197 contentColor = contentColor,
1198 secondaryContentColor = secondaryContentColor,
1199 iconColor = iconColor,
1200 disabledBackgroundColor = disabledBackgroundColor,
1201 disabledContentColor = disabledContentColor,
1202 disabledSecondaryContentColor = disabledSecondaryContentColor,
1203 disabledIconColor = disabledIconColor
1204 )
1205
1206 /**
1207 * Creates a [ChipColors] where all of the values are explicitly defined.
1208 *
1209 * @param backgroundPainter The background painter of this [Chip] when enabled
1210 * @param contentColor The content color of this [Chip] when enabled
1211 * @param secondaryContentColor The content color of this [Chip] when enabled
1212 * @param iconColor The content color of this [Chip] when enabled
1213 * @param disabledBackgroundPainter The background painter of this [Chip] when not enabled
1214 * @param disabledContentColor The content color of this [Chip] when not enabled
1215 * @param disabledSecondaryContentColor The content color of this [Chip] when not enabled
1216 * @param disabledIconColor The content color of this [Chip] when not enabled
1217 */
1218 @ExperimentalWearMaterialApi
1219 public fun chipColors(
1220 backgroundPainter: Painter,
1221 contentColor: Color,
1222 secondaryContentColor: Color,
1223 iconColor: Color,
1224 disabledBackgroundPainter: Painter,
1225 disabledContentColor: Color,
1226 disabledSecondaryContentColor: Color,
1227 disabledIconColor: Color,
1228 ): ChipColors =
1229 DefaultChipColors(
1230 backgroundPainter = backgroundPainter,
1231 contentColor = contentColor,
1232 secondaryContentColor = secondaryContentColor,
1233 iconColor = iconColor,
1234 disabledBackgroundPainter = disabledBackgroundPainter,
1235 disabledContentColor = disabledContentColor,
1236 disabledSecondaryContentColor = disabledSecondaryContentColor,
1237 disabledIconColor = disabledIconColor
1238 )
1239 }
1240
1241 /** Default [ChipColors] implementation. */
1242 @Immutable
1243 internal class DefaultChipColors(
1244 private val backgroundPainter: Painter,
1245 private val contentColor: Color,
1246 private val secondaryContentColor: Color,
1247 private val iconColor: Color,
1248 private val disabledBackgroundPainter: Painter,
1249 private val disabledContentColor: Color,
1250 private val disabledSecondaryContentColor: Color,
1251 private val disabledIconColor: Color
1252 ) : ChipColors {
1253
1254 constructor(
1255 backgroundColor: Color,
1256 contentColor: Color,
1257 secondaryContentColor: Color,
1258 iconColor: Color,
1259 disabledBackgroundColor: Color,
1260 disabledContentColor: Color,
1261 disabledSecondaryContentColor: Color,
1262 disabledIconColor: Color
1263 ) : this(
1264 ColorPainter(backgroundColor),
1265 contentColor,
1266 secondaryContentColor,
1267 iconColor,
1268 ColorPainter(disabledBackgroundColor),
1269 disabledContentColor,
1270 disabledSecondaryContentColor,
1271 disabledIconColor
1272 )
1273
1274 @Composable
backgroundnull1275 override fun background(enabled: Boolean): State<Painter> {
1276 return rememberUpdatedState(if (enabled) backgroundPainter else disabledBackgroundPainter)
1277 }
1278
1279 @Composable
contentColornull1280 override fun contentColor(enabled: Boolean): State<Color> {
1281 return rememberUpdatedState(if (enabled) contentColor else disabledContentColor)
1282 }
1283
1284 @Composable
secondaryContentColornull1285 override fun secondaryContentColor(enabled: Boolean): State<Color> {
1286 return rememberUpdatedState(
1287 if (enabled) secondaryContentColor else disabledSecondaryContentColor
1288 )
1289 }
1290
1291 @Composable
iconColornull1292 override fun iconColor(enabled: Boolean): State<Color> {
1293 return rememberUpdatedState(if (enabled) iconColor else disabledIconColor)
1294 }
1295
equalsnull1296 override fun equals(other: Any?): Boolean {
1297 if (this === other) return true
1298 if (other == null) return false
1299 if (this::class != other::class) return false
1300
1301 other as DefaultChipColors
1302
1303 if (backgroundPainter != other.backgroundPainter) return false
1304 if (contentColor != other.contentColor) return false
1305 if (secondaryContentColor != other.secondaryContentColor) return false
1306 if (iconColor != other.iconColor) return false
1307 if (disabledBackgroundPainter != other.disabledBackgroundPainter) return false
1308 if (disabledContentColor != other.disabledContentColor) return false
1309 if (disabledSecondaryContentColor != other.disabledSecondaryContentColor) return false
1310 if (disabledIconColor != other.disabledIconColor) return false
1311
1312 return true
1313 }
1314
hashCodenull1315 override fun hashCode(): Int {
1316 var result = backgroundPainter.hashCode()
1317 result = 31 * result + contentColor.hashCode()
1318 result = 31 * result + secondaryContentColor.hashCode()
1319 result = 31 * result + iconColor.hashCode()
1320 result = 31 * result + disabledBackgroundPainter.hashCode()
1321 result = 31 * result + disabledContentColor.hashCode()
1322 result = 31 * result + disabledSecondaryContentColor.hashCode()
1323 result = 31 * result + disabledIconColor.hashCode()
1324 return result
1325 }
1326 }
1327
1328 /** Default [ChipBorder] implementation. */
1329 @Immutable
1330 private class DefaultChipBorder(
1331 private val borderStroke: BorderStroke? = null,
1332 private val disabledBorderStroke: BorderStroke? = null
1333 ) : ChipBorder {
1334 @Composable
borderStrokenull1335 override fun borderStroke(enabled: Boolean): State<BorderStroke?> {
1336 return rememberUpdatedState(if (enabled) borderStroke else disabledBorderStroke)
1337 }
1338
equalsnull1339 override fun equals(other: Any?): Boolean {
1340 if (this === other) return true
1341 if (other == null) return false
1342 if (this::class != other::class) return false
1343
1344 other as DefaultChipBorder
1345
1346 if (borderStroke != other.borderStroke) return false
1347 if (disabledBorderStroke != other.disabledBorderStroke) return false
1348
1349 return true
1350 }
1351
hashCodenull1352 override fun hashCode(): Int {
1353 var result = borderStroke.hashCode()
1354 result = 31 * result + disabledBorderStroke.hashCode()
1355 return result
1356 }
1357 }
1358
1359 @Composable
chipSizeModifiernull1360 private fun Modifier.chipSizeModifier() =
1361 this.defaultMinSize(minHeight = ChipDefaults.Height).height(IntrinsicSize.Min)
1362
1363 @Composable private fun Modifier.compactChipModifier() = this.height(ChipDefaults.CompactChipHeight)
1364
1365 @Composable
1366 private fun ChipImpl(
1367 onClick: () -> Unit,
1368 colors: ChipColors,
1369 border: ChipBorder?,
1370 modifier: Modifier,
1371 enabled: Boolean,
1372 contentPadding: PaddingValues,
1373 shape: Shape,
1374 interactionSource: MutableInteractionSource?,
1375 role: Role? = Role.Button,
1376 content: @Composable RowScope.() -> Unit,
1377 ) {
1378 val borderStroke = border?.borderStroke(enabled)?.value
1379 val borderModifier =
1380 if (borderStroke != null) modifier.border(border = borderStroke, shape = shape)
1381 else modifier
1382 Row(
1383 modifier =
1384 borderModifier
1385 .clip(shape = shape)
1386 .width(intrinsicSize = IntrinsicSize.Max)
1387 .paint(painter = colors.background(enabled).value, contentScale = ContentScale.Crop)
1388 .clickable(
1389 enabled = enabled,
1390 onClick = onClick,
1391 role = role,
1392 indication = ripple(),
1393 interactionSource = interactionSource,
1394 )
1395 .padding(contentPadding),
1396 content =
1397 provideScopeContent(
1398 colors.contentColor(enabled = enabled),
1399 MaterialTheme.typography.button,
1400 content
1401 )
1402 )
1403 }
1404
1405 @Composable
ChipImplnull1406 private fun ChipImpl(
1407 label: @Composable RowScope.() -> Unit,
1408 labelTypography: TextStyle,
1409 onClick: () -> Unit,
1410 modifier: Modifier,
1411 secondaryLabel: (@Composable RowScope.() -> Unit)?,
1412 icon: (@Composable BoxScope.() -> Unit)?,
1413 colors: ChipColors,
1414 enabled: Boolean,
1415 interactionSource: MutableInteractionSource?,
1416 contentPadding: PaddingValues,
1417 shape: Shape,
1418 border: ChipBorder?,
1419 defaultIconSpacing: Dp
1420 ) {
1421 ChipImpl(
1422 onClick = onClick,
1423 modifier = modifier,
1424 colors = colors,
1425 border = border,
1426 enabled = enabled,
1427 contentPadding = contentPadding,
1428 shape = shape,
1429 interactionSource = interactionSource,
1430 ) {
1431 Row(
1432 verticalAlignment = Alignment.CenterVertically,
1433 // Fill the container height but not its width as chips have fixed size height but we
1434 // want them to be able to fit their content
1435 modifier = Modifier.fillMaxHeight()
1436 ) {
1437 if (icon != null) {
1438 Box(
1439 modifier = Modifier.wrapContentSize(align = Alignment.Center),
1440 content = provideIcon(colors.iconColor(enabled), icon)
1441 )
1442 Spacer(modifier = Modifier.size(defaultIconSpacing))
1443 }
1444 Column {
1445 Row(
1446 content =
1447 provideScopeContent(colors.contentColor(enabled), labelTypography, label)
1448 )
1449 secondaryLabel?.let {
1450 Row(
1451 content =
1452 provideScopeContent(
1453 colors.secondaryContentColor(enabled),
1454 MaterialTheme.typography.caption2,
1455 secondaryLabel
1456 )
1457 )
1458 }
1459 }
1460 }
1461 }
1462 }
1463