1 /*
2 * Copyright 2023 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 * https://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 com.google.android.horologist.compose.material
18
19 import androidx.annotation.DrawableRes
20 import androidx.compose.foundation.layout.size
21 import androidx.compose.runtime.Composable
22 import androidx.compose.ui.Alignment
23 import androidx.compose.ui.Modifier
24 import androidx.compose.ui.graphics.vector.ImageVector
25 import androidx.compose.ui.unit.Dp
26 import androidx.wear.compose.material.Button
27 import androidx.wear.compose.material.ButtonColors
28 import androidx.wear.compose.material.ButtonDefaults
29 import androidx.wear.compose.material.ButtonDefaults.DefaultButtonSize
30 import androidx.wear.compose.material.ButtonDefaults.DefaultIconSize
31 import androidx.wear.compose.material.ButtonDefaults.LargeButtonSize
32 import androidx.wear.compose.material.ButtonDefaults.LargeIconSize
33 import androidx.wear.compose.material.ButtonDefaults.SmallButtonSize
34 import androidx.wear.compose.material.ButtonDefaults.SmallIconSize
35 import com.google.android.horologist.annotations.ExperimentalHorologistApi
36
37 /**
38 * This component is an alternative to [Button], providing the following:
39 * - a convenient way of providing an icon and choosing its size from a range of sizes recommended
40 * by the Wear guidelines;
41 */
42 @ExperimentalHorologistApi
43 @Composable
Buttonnull44 public fun Button(
45 imageVector: ImageVector,
46 contentDescription: String,
47 onClick: () -> Unit,
48 modifier: Modifier = Modifier,
49 colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
50 buttonSize: ButtonSize = ButtonSize.Default,
51 iconRtlMode: IconRtlMode = IconRtlMode.Default,
52 enabled: Boolean = true,
53 ) {
54 Button(
55 icon = imageVector,
56 contentDescription = contentDescription,
57 onClick = onClick,
58 modifier = modifier,
59 colors = colors,
60 buttonSize = buttonSize,
61 iconRtlMode = iconRtlMode,
62 enabled = enabled,
63 )
64 }
65
66 /**
67 * This component is an alternative to [Button], providing the following:
68 * - a convenient way of providing an icon and choosing its size from a range of sizes recommended
69 * by the Wear guidelines;
70 */
71 @ExperimentalHorologistApi
72 @Composable
Buttonnull73 public fun Button(
74 @DrawableRes id: Int,
75 contentDescription: String,
76 onClick: () -> Unit,
77 modifier: Modifier = Modifier,
78 colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
79 buttonSize: ButtonSize = ButtonSize.Default,
80 iconRtlMode: IconRtlMode = IconRtlMode.Default,
81 enabled: Boolean = true,
82 ) {
83 Button(
84 icon = id,
85 contentDescription = contentDescription,
86 onClick = onClick,
87 modifier = modifier,
88 colors = colors,
89 buttonSize = buttonSize,
90 iconRtlMode = iconRtlMode,
91 enabled = enabled,
92 )
93 }
94
95 @OptIn(ExperimentalHorologistApi::class)
96 @Composable
Buttonnull97 internal fun Button(
98 icon: Any,
99 contentDescription: String,
100 onClick: () -> Unit,
101 modifier: Modifier = Modifier,
102 colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
103 buttonSize: ButtonSize = ButtonSize.Default,
104 iconRtlMode: IconRtlMode = IconRtlMode.Default,
105 enabled: Boolean = true,
106 ) {
107 Button(
108 onClick = onClick,
109 modifier = modifier.size(buttonSize.tapTargetSize),
110 enabled = enabled,
111 colors = colors,
112 ) {
113 val iconModifier = Modifier
114 .size(buttonSize.iconSize)
115 .align(Alignment.Center)
116
117 Icon(
118 icon = icon,
119 contentDescription = contentDescription,
120 modifier = iconModifier,
121 rtlMode = iconRtlMode,
122 )
123 }
124 }
125
126 @ExperimentalHorologistApi
127 public sealed class ButtonSize(
128 public val iconSize: Dp,
129 public val tapTargetSize: Dp,
130 ) {
131 public object Default :
132 ButtonSize(iconSize = DefaultIconSize, tapTargetSize = DefaultButtonSize)
133
134 public object Large : ButtonSize(iconSize = LargeIconSize, tapTargetSize = LargeButtonSize)
135 public object Small : ButtonSize(iconSize = SmallIconSize, tapTargetSize = SmallButtonSize)
136
137 /**
138 * Custom sizes should follow the [accessibility principles and guidance for touch targets](https://developer.android.com/training/wearables/accessibility#set-minimum).
139 */
140 public data class Custom(val customIconSize: Dp, val customTapTargetSize: Dp) :
141 ButtonSize(iconSize = customIconSize, tapTargetSize = customTapTargetSize)
142 }
143
144