Skip to content

Commit a68d4a7

Browse files
authored
Merge branch 'main' into clickable
2 parents db0dfe0 + 9d3cec9 commit a68d4a7

File tree

63 files changed

+440
-191
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+440
-191
lines changed

compose-material/api/current.api

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
package com.google.android.horologist.compose.material {
33

44
public final class AlertDialogKt {
5-
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void AlertContent(kotlin.jvm.functions.Function0<kotlin.Unit>? onCancelButtonClick, kotlin.jvm.functions.Function0<kotlin.Unit>? onOKButtonClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional String? title, optional String? message, optional String okButtonContentDescription, optional String cancelButtonContentDescription, optional com.google.android.horologist.compose.layout.ScalingLazyColumnState columnState, optional boolean showPositionIndicator);
6-
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void AlertDialog(kotlin.jvm.functions.Function0<kotlin.Unit> onCancelButtonClick, kotlin.jvm.functions.Function0<kotlin.Unit> onOKButtonClick, boolean showDialog, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional String? title, optional String? message, optional String okButtonContentDescription, optional String cancelButtonContentDescription, optional com.google.android.horologist.compose.layout.ScalingLazyColumnState columnState);
5+
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void AlertContent(optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onOk, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional String? title, optional String? message, optional String okButtonContentDescription, optional String cancelButtonContentDescription, optional com.google.android.horologist.compose.layout.ScalingLazyColumnState state, optional boolean showPositionIndicator, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
6+
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void AlertDialog(boolean showDialog, kotlin.jvm.functions.Function0<kotlin.Unit> onDismiss, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional String? title, optional String? message, optional com.google.android.horologist.compose.layout.ScalingLazyColumnState state, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
7+
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void AlertDialog(boolean showDialog, kotlin.jvm.functions.Function0<kotlin.Unit> onCancel, kotlin.jvm.functions.Function0<kotlin.Unit> onOk, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional String? title, optional String? message, optional String okButtonContentDescription, optional String cancelButtonContentDescription, optional com.google.android.horologist.compose.layout.ScalingLazyColumnState state, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
78
}
89

910
public final class ButtonKt {
@@ -92,7 +93,7 @@ package com.google.android.horologist.compose.material {
9293
}
9394

9495
public final class ResponsiveDialogKt {
95-
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void ResponsiveDialogContent(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit>? message, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onOkButtonClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCancelButtonClick, optional String okButtonContentDescription, optional String cancelButtonContentDescription, optional com.google.android.horologist.compose.layout.ScalingLazyColumnState state, optional boolean showPositionIndicator, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
96+
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void ResponsiveDialogContent(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit>? message, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onOk, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel, optional String okButtonContentDescription, optional String cancelButtonContentDescription, optional com.google.android.horologist.compose.layout.ScalingLazyColumnState state, optional boolean showPositionIndicator, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
9697
}
9798

9899
public final class SplitToggleChipKt {

compose-material/src/debug/java/com/google/android/horologist/compose/material/AlertDialogPreview.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ fun AlertDialogPreview() {
2525
AlertContent(
2626
title = "Title",
2727
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
28-
onCancelButtonClick = { },
29-
onOKButtonClick = { },
28+
onCancel = { },
29+
onOk = { },
3030
okButtonContentDescription = "Ok",
3131
cancelButtonContentDescription = "Cancel",
3232
)
@@ -43,8 +43,8 @@ fun AlertDialogWithLongBodyPreview() {
4343
"irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla " +
4444
"pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia " +
4545
"deserunt mollit anim id est laborum.",
46-
onCancelButtonClick = { },
47-
onOKButtonClick = { },
46+
onCancel = { },
47+
onOk = { },
4848
okButtonContentDescription = "Ok",
4949
cancelButtonContentDescription = "Cancel",
5050
)

compose-material/src/main/java/com/google/android/horologist/compose/material/AlertDialog.kt

+90-16
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,20 @@
1616

1717
package com.google.android.horologist.compose.material
1818

19+
import androidx.compose.foundation.layout.fillMaxWidth
1920
import androidx.compose.runtime.Composable
21+
import androidx.compose.runtime.remember
2022
import androidx.compose.ui.Modifier
23+
import androidx.compose.ui.platform.LocalConfiguration
24+
import androidx.compose.ui.platform.LocalDensity
2125
import androidx.compose.ui.res.stringResource
26+
import androidx.compose.ui.text.rememberTextMeasurer
2227
import androidx.compose.ui.text.style.TextAlign
2328
import androidx.compose.ui.text.style.TextOverflow
29+
import androidx.compose.ui.unit.Constraints
30+
import androidx.compose.ui.unit.dp
31+
import androidx.wear.compose.foundation.lazy.ScalingLazyListScope
32+
import androidx.wear.compose.material.LocalTextStyle
2433
import androidx.wear.compose.material.MaterialTheme
2534
import androidx.wear.compose.material.Text
2635
import androidx.wear.compose.material.dialog.Dialog
@@ -32,65 +41,112 @@ import com.google.android.horologist.compose.layout.rememberColumnState
3241
/**
3342
* This component is an alternative to [AlertContent], providing the following:
3443
* - a convenient way of passing a title and a message;
44+
* - additional content can be specified between the message and the buttons
3545
* - default positive and negative buttons;
3646
* - wrapped in a [Dialog];
3747
*/
3848
@ExperimentalHorologistApi
3949
@Composable
4050
public fun AlertDialog(
41-
onCancelButtonClick: () -> Unit,
42-
onOKButtonClick: () -> Unit,
4351
showDialog: Boolean,
52+
onCancel: () -> Unit,
53+
onOk: () -> Unit,
4454
modifier: Modifier = Modifier,
4555
icon: @Composable (() -> Unit)? = null,
4656
title: String? = null,
4757
message: String? = null,
4858
okButtonContentDescription: String = stringResource(android.R.string.ok),
4959
cancelButtonContentDescription: String = stringResource(android.R.string.cancel),
50-
columnState: ScalingLazyColumnState = rememberColumnState(
60+
state: ScalingLazyColumnState = rememberColumnState(
5161
ScalingLazyColumnDefaults.responsive(),
5262
),
63+
content: (ScalingLazyListScope.() -> Unit)? = null,
5364
) {
5465
Dialog(
5566
showDialog = showDialog,
56-
onDismissRequest = onCancelButtonClick,
67+
onDismissRequest = onCancel,
5768
modifier = modifier,
58-
scrollState = columnState.state,
69+
scrollState = state.state,
5970
) {
6071
AlertContent(
6172
icon = icon,
6273
title = title,
6374
message = message,
64-
onCancelButtonClick = onCancelButtonClick,
65-
onOKButtonClick = onOKButtonClick,
75+
content = content,
76+
onCancel = onCancel,
77+
onOk = onOk,
6678
okButtonContentDescription = okButtonContentDescription,
6779
cancelButtonContentDescription = cancelButtonContentDescription,
68-
columnState = columnState,
80+
state = state,
6981
showPositionIndicator = false,
7082
)
7183
}
7284
}
7385

86+
/**
87+
* This component is an alternative to [AlertContent], providing the following:
88+
* - a convenient way of passing a title and a message;
89+
* - slot for scrollable content (including stack of Chips for options);
90+
* - wrapped in a [Dialog];
91+
*/
92+
@ExperimentalHorologistApi
93+
@Composable
94+
public fun AlertDialog(
95+
showDialog: Boolean,
96+
onDismiss: () -> Unit,
97+
modifier: Modifier = Modifier,
98+
icon: @Composable (() -> Unit)? = null,
99+
title: String? = null,
100+
message: String? = null,
101+
state: ScalingLazyColumnState = rememberColumnState(
102+
ScalingLazyColumnDefaults.responsive(),
103+
),
104+
content: (ScalingLazyListScope.() -> Unit)? = null,
105+
) {
106+
Dialog(
107+
showDialog = showDialog,
108+
onDismissRequest = onDismiss,
109+
modifier = modifier,
110+
scrollState = state.state,
111+
) {
112+
AlertContent(
113+
icon = icon,
114+
title = title,
115+
message = message,
116+
content = content,
117+
state = state,
118+
showPositionIndicator = true,
119+
)
120+
}
121+
}
122+
74123
@ExperimentalHorologistApi
75124
@Composable
76125
public fun AlertContent(
77-
onCancelButtonClick: (() -> Unit)?,
78-
onOKButtonClick: (() -> Unit)?,
126+
onCancel: (() -> Unit)? = null,
127+
onOk: (() -> Unit)? = null,
79128
icon: @Composable (() -> Unit)? = null,
80129
title: String? = null,
81130
message: String? = null,
82131
okButtonContentDescription: String = stringResource(android.R.string.ok),
83132
cancelButtonContentDescription: String = stringResource(android.R.string.cancel),
84-
columnState: ScalingLazyColumnState = rememberColumnState(
133+
state: ScalingLazyColumnState = rememberColumnState(
85134
ScalingLazyColumnDefaults.responsive(),
86135
),
87136
showPositionIndicator: Boolean = true,
137+
content: (ScalingLazyListScope.() -> Unit)? = null,
88138
) {
139+
val density = LocalDensity.current
140+
val maxScreenWidthPx = with(density) {
141+
LocalConfiguration.current.screenWidthDp.dp.toPx()
142+
}
143+
89144
ResponsiveDialogContent(
90145
icon = icon,
91146
title = title?.let {
92147
{
93148
Text(
149+
modifier = Modifier.fillMaxWidth(),
94150
text = it,
95151
color = MaterialTheme.colors.onBackground,
96152
textAlign = TextAlign.Center,
@@ -101,19 +157,37 @@ public fun AlertContent(
101157
},
102158
message = message?.let {
103159
{
160+
// Should message be start or center aligned?
161+
val textMeasurer = rememberTextMeasurer()
162+
val textStyle = LocalTextStyle.current
163+
val totalPaddingPercentage = globalHorizontalPadding + messageExtraHorizontalPadding
164+
val lineCount = remember(it, density, textStyle, textMeasurer) {
165+
textMeasurer.measure(
166+
text = it,
167+
style = textStyle,
168+
constraints = Constraints(
169+
// Available width is reduced by responsive dialog horizontal padding.
170+
maxWidth = (
171+
maxScreenWidthPx * (1f - totalPaddingPercentage * 2f / 100f)
172+
).toInt(),
173+
),
174+
).lineCount
175+
}
176+
val textAlign = if (lineCount <= 3) TextAlign.Center else TextAlign.Start
104177
Text(
178+
modifier = Modifier.fillMaxWidth(),
105179
text = it,
106180
color = MaterialTheme.colors.onBackground,
107-
textAlign = TextAlign.Center,
108-
maxLines = 3,
181+
textAlign = textAlign,
109182
)
110183
}
111184
},
112-
onOkButtonClick = onOKButtonClick,
113-
onCancelButtonClick = onCancelButtonClick,
185+
content = content,
186+
onOk = onOk,
187+
onCancel = onCancel,
114188
okButtonContentDescription = okButtonContentDescription,
115189
cancelButtonContentDescription = cancelButtonContentDescription,
116-
state = columnState,
190+
state = state,
117191
showPositionIndicator = showPositionIndicator,
118192
)
119193
}

compose-material/src/main/java/com/google/android/horologist/compose/material/ResponsiveDialog.kt

+26-14
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ public fun ResponsiveDialogContent(
5353
icon: @Composable (() -> Unit)? = null,
5454
title: @Composable (() -> Unit)? = null,
5555
message: @Composable (() -> Unit)? = null,
56-
onOkButtonClick: (() -> Unit)? = null,
57-
onCancelButtonClick: (() -> Unit)? = null,
56+
onOk: (() -> Unit)? = null,
57+
onCancel: (() -> Unit)? = null,
5858
okButtonContentDescription: String = stringResource(R.string.ok),
5959
cancelButtonContentDescription: String = stringResource(R.string.cancel),
6060
state: ScalingLazyColumnState =
@@ -89,12 +89,9 @@ public fun ResponsiveDialogContent(
8989
CompositionLocalProvider(
9090
LocalTextStyle provides MaterialTheme.typography.title3,
9191
) {
92-
// Compute the actual padding needed to get an extra 8.84%,
93-
// inside of the global 5.2% padding
94-
val extraPadding = 8.84f / (100f - 2f * 5.2f)
9592
Box(
9693
Modifier
97-
.fillMaxWidth(1f - 2f * extraPadding)
94+
.fillMaxWidth(titleMaxWidthFraction)
9895
.padding(bottom = 8.dp), // 12.dp below icon
9996
) { it() }
10097
}
@@ -108,18 +105,15 @@ public fun ResponsiveDialogContent(
108105
}
109106
message?.let {
110107
item {
111-
// Compute the actual padding needed to get an extra 4.16%,
112-
// inside of the global 5.2% padding
113-
val extraPadding = 4.16f / (100f - 2f * 5.2f)
114108
Box(
115-
Modifier.fillMaxWidth(1f - 2f * extraPadding),
109+
Modifier.fillMaxWidth(messageMaxWidthFraction),
116110
) { it() }
117111
}
118112
}
119113
content?.let {
120114
it()
121115
}
122-
if (onOkButtonClick != null || onCancelButtonClick != null) {
116+
if (onOk != null || onCancel != null) {
123117
item {
124118
Row(
125119
Modifier
@@ -133,19 +127,19 @@ public fun ResponsiveDialogContent(
133127
),
134128
verticalAlignment = Alignment.CenterVertically,
135129
) {
136-
onCancelButtonClick?.let {
130+
onCancel?.let {
137131
Button(
138132
imageVector = Icons.Default.Close,
139133
contentDescription = cancelButtonContentDescription,
140134
onClick = it,
141135
colors = ButtonDefaults.secondaryButtonColors(),
142136
)
143137
}
144-
onOkButtonClick?.let {
138+
onOk?.let {
145139
Button(
146140
imageVector = Icons.Default.Check,
147141
contentDescription = okButtonContentDescription,
148-
onClick = onOkButtonClick,
142+
onClick = onOk,
149143
)
150144
}
151145
}
@@ -155,3 +149,21 @@ public fun ResponsiveDialogContent(
155149
}
156150
}
157151
}
152+
153+
internal const val globalHorizontalPadding = 5.2f
154+
internal const val messageExtraHorizontalPadding = 4.16f
155+
internal const val titleExtraHorizontalPadding = 8.84f
156+
157+
// Fraction of the max available width that message should take (after global and message padding)
158+
internal val messageMaxWidthFraction = 1f - 2f * calculatePaddingFraction(
159+
messageExtraHorizontalPadding,
160+
)
161+
162+
// Fraction of the max available width that title should take (after global and message padding)
163+
internal val titleMaxWidthFraction = 1f - 2f * calculatePaddingFraction(
164+
titleExtraHorizontalPadding,
165+
)
166+
167+
// Calculate total padding given global padding and additional padding required inside that.
168+
internal fun calculatePaddingFraction(extraPadding: Float) =
169+
extraPadding / (100f - 2f * globalHorizontalPadding)

datalayer/phone-ui/src/main/java/com/google/android/horologist/datalayer/phone/ui/prompt/installapp/InstallAppBottomSheetActivity.kt

+13-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package com.google.android.horologist.datalayer.phone.ui.prompt.installapp
1818

1919
import android.content.Context
2020
import android.content.Intent
21+
import android.os.Build
2122
import android.os.Bundle
2223
import androidx.activity.ComponentActivity
2324
import androidx.activity.compose.setContent
@@ -77,22 +78,32 @@ internal class InstallAppBottomSheetActivity : ComponentActivity() {
7778
try {
7879
installAppBottomSheetState.hide()
7980
} finally {
80-
finish()
81+
finishWithoutAnimation()
8182
}
8283
}
8384
},
8485
onConfirmation = {
8586
this.launchPlay(appPackageName)
8687

8788
setResult(RESULT_OK)
88-
finish()
89+
finishWithoutAnimation()
8990
},
9091
sheetState = installAppBottomSheetState,
9192
)
9293
}
9394
}
9495
}
9596

97+
private fun finishWithoutAnimation() {
98+
finish()
99+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
100+
overrideActivityTransition(OVERRIDE_TRANSITION_CLOSE, 0, 0)
101+
} else {
102+
@Suppress("DEPRECATION")
103+
overridePendingTransition(0, 0)
104+
}
105+
}
106+
96107
internal companion object {
97108
fun getIntent(
98109
context: Context,

0 commit comments

Comments
 (0)