Skip to content

Commit d348638

Browse files
committed
Add Map buttons
1 parent 3bc4b00 commit d348638

File tree

7 files changed

+89
-24
lines changed

7 files changed

+89
-24
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24">
6+
<path
7+
android:pathData="M3,12C3,11.448 3.448,11 4,11H20C20.552,11 21,11.448 21,12C21,12.552 20.552,13 20,13H4C3.448,13 3,12.552 3,12Z"
8+
android:fillColor="#19191C" />
9+
</vector>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24">
6+
<path
7+
android:pathData="M12,3C12.552,3 13,3.448 13,4V11H20C20.552,11 21,11.448 21,12C21,12.552 20.552,13 20,13H13V20C13,20.552 12.552,21 12,21C11.448,21 11,20.552 11,20V13H4C3.448,13 3,12.552 3,12C3,11.448 3.448,11 4,11H11V4C11,3.448 11.448,3 12,3Z"
8+
android:fillColor="#19191C"/>
9+
</vector>

shared/src/commonMain/composeResources/values-de/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ Wir verarbeiten Ihre Daten gemäß dem Datenschutzhinweis der App. Sie können I
129129
<string name="map_title">Karte</string>
130130
<string name="map_ground_floor">Erdgeschoss</string>
131131
<string name="map_first_floor">Erster Stock</string>
132+
<string name="map_zoom_in">Hineinzoomen</string>
133+
<string name="map_zoom_out">Herauszoomen</string>
132134

133135
<string name="speakers_title">Sprecher</string>
134136
<string name="speakers_error_no_results">Keine Ergebnisse</string>

shared/src/commonMain/composeResources/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ We will process your data in accordance with the App Privacy Notice. You can adj
129129
<string name="map_title">Map</string>
130130
<string name="map_ground_floor">Ground floor</string>
131131
<string name="map_first_floor">First floor</string>
132+
<string name="map_zoom_in">Zoom in</string>
133+
<string name="map_zoom_out">Zoom out</string>
132134

133135
<string name="speakers_title">Speakers</string>
134136
<string name="speakers_error_no_results">No results</string>

shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/MapScreen.kt

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import androidx.compose.foundation.background
1111
import androidx.compose.foundation.gestures.detectTapGestures
1212
import androidx.compose.foundation.gestures.rememberTransformableState
1313
import androidx.compose.foundation.gestures.transformable
14+
import androidx.compose.foundation.layout.Arrangement
15+
import androidx.compose.foundation.layout.Box
1416
import androidx.compose.foundation.layout.Column
1517
import androidx.compose.foundation.layout.fillMaxSize
1618
import androidx.compose.foundation.layout.padding
@@ -24,6 +26,7 @@ import androidx.compose.runtime.saveable.Saver
2426
import androidx.compose.runtime.saveable.SaverScope
2527
import androidx.compose.runtime.saveable.rememberSaveable
2628
import androidx.compose.runtime.setValue
29+
import androidx.compose.ui.Alignment
2730
import androidx.compose.ui.Modifier
2831
import androidx.compose.ui.draw.clipToBounds
2932
import androidx.compose.ui.geometry.Offset
@@ -40,11 +43,17 @@ import org.jetbrains.compose.resources.StringResource
4043
import org.jetbrains.compose.resources.stringResource
4144
import org.jetbrains.kotlinconf.generated.resources.Res
4245
import org.jetbrains.kotlinconf.generated.resources.arrow_left_24
46+
import org.jetbrains.kotlinconf.generated.resources.bookmark_24
4347
import org.jetbrains.kotlinconf.generated.resources.map_first_floor
4448
import org.jetbrains.kotlinconf.generated.resources.map_ground_floor
4549
import org.jetbrains.kotlinconf.generated.resources.map_title
50+
import org.jetbrains.kotlinconf.generated.resources.map_zoom_in
51+
import org.jetbrains.kotlinconf.generated.resources.map_zoom_out
52+
import org.jetbrains.kotlinconf.generated.resources.minus_24
4653
import org.jetbrains.kotlinconf.generated.resources.navigate_back
54+
import org.jetbrains.kotlinconf.generated.resources.plus_24
4755
import org.jetbrains.kotlinconf.ui.components.Divider
56+
import org.jetbrains.kotlinconf.ui.components.IconButton
4857
import org.jetbrains.kotlinconf.ui.components.MainHeaderTitleBar
4958
import org.jetbrains.kotlinconf.ui.components.Switcher
5059
import org.jetbrains.kotlinconf.ui.components.TopMenuButton
@@ -206,6 +215,8 @@ private fun Map(
206215
val validOffsetX = (-svg.width * 0.5f)..(svg.width * 0.5f)
207216
val validOffsetY = (-svg.height * 0.5f)..(svg.height * 0.5f)
208217

218+
val spec = tween<Float>(500, easing = EaseOutCubic)
219+
209220
val interactiveModifiers = if (!interactive) {
210221
Modifier
211222
} else {
@@ -224,8 +235,6 @@ private fun Map(
224235

225236
detectTapGestures(
226237
onDoubleTap = { tapOffset ->
227-
val spec = tween<Float>(500, easing = EaseOutCubic)
228-
229238
if (scale.value >= zoomRange.endInclusive - 0.1f) {
230239
scope.launch { scale.animateTo(initialZoom, spec) }
231240
} else {
@@ -247,23 +256,58 @@ private fun Map(
247256
}
248257
}
249258

250-
Canvas(
251-
modifier
252-
.clipToBounds()
253-
.fillMaxSize()
254-
.then(interactiveModifiers)
255-
) {
256-
translate(
257-
left = offsetX.value + (size.width - svg.width) / 2,
258-
top = offsetY.value + (size.height - svg.height) / 2,
259+
Box(Modifier.fillMaxSize()) {
260+
Canvas(
261+
modifier
262+
.clipToBounds()
263+
.fillMaxSize()
264+
.then(interactiveModifiers)
259265
) {
260-
scale(
261-
scale = scale.value,
262-
pivot = Offset(svg.width / 2 - offsetX.value, svg.height / 2 - offsetY.value),
266+
translate(
267+
left = offsetX.value + (size.width - svg.width) / 2,
268+
top = offsetY.value + (size.height - svg.height) / 2,
263269
) {
264-
svg.renderTo(this)
270+
scale(
271+
scale = scale.value,
272+
pivot = Offset(svg.width / 2 - offsetX.value, svg.height / 2 - offsetY.value),
273+
) {
274+
svg.renderTo(this)
275+
}
265276
}
266277
}
278+
Column(
279+
modifier = Modifier
280+
.align(Alignment.BottomEnd)
281+
.padding(bottom = 24.dp, end = 12.dp),
282+
verticalArrangement = Arrangement.spacedBy(16.dp)
283+
) {
284+
IconButton(
285+
icon = Res.drawable.plus_24,
286+
enabled = scale.targetValue < zoomRange.endInclusive,
287+
onClick = {
288+
scope.launch {
289+
scale.animateTo(
290+
targetValue = (scale.value * 2f).coerceIn(zoomRange),
291+
animationSpec = spec,
292+
)
293+
}
294+
},
295+
contentDescription = stringResource(Res.string.map_zoom_in),
296+
)
297+
IconButton(
298+
icon = Res.drawable.minus_24,
299+
enabled = scale.targetValue > zoomRange.start,
300+
onClick = {
301+
scope.launch {
302+
scale.animateTo(
303+
targetValue = (scale.value / 2f).coerceIn(zoomRange),
304+
animationSpec = spec,
305+
)
306+
}
307+
},
308+
contentDescription = stringResource(Res.string.map_zoom_out),
309+
)
310+
}
267311
}
268312
}
269313

ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Button.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ fun Button(
5454
.heightIn(min = 56.dp)
5555
.border(width = 1.dp, color = borderColor, shape = ButtonShape)
5656
.clip(ButtonShape)
57-
.then(if (enabled) Modifier.clickable(onClick = onClick) else Modifier)
58-
.semantics { role = Role.Button }
57+
.clickable(enabled = enabled, onClick = onClick, role = Role.Button)
5958
.background(backgroundColor)
6059
.padding(horizontal = 32.dp),
6160
contentAlignment = Alignment.Center,

ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/IconButton.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import androidx.compose.ui.Alignment
1616
import androidx.compose.ui.Modifier
1717
import androidx.compose.ui.draw.clip
1818
import androidx.compose.ui.graphics.Color
19+
import androidx.compose.ui.semantics.Role
1920
import androidx.compose.ui.semantics.contentDescription
2021
import androidx.compose.ui.semantics.semantics
2122
import androidx.compose.ui.tooling.preview.Preview
@@ -32,8 +33,8 @@ fun IconButton(
3233
icon: DrawableResource,
3334
enabled: Boolean,
3435
onClick: () -> Unit,
35-
contentDescription: String,
3636
modifier: Modifier = Modifier,
37+
contentDescription: String? = null,
3738
) {
3839
val strokeColor by animateColorAsState(
3940
if (enabled) KotlinConfTheme.colors.strokeHalf
@@ -46,18 +47,17 @@ fun IconButton(
4647

4748
Box(
4849
modifier
49-
.then(if (enabled) Modifier.clickable(onClick = onClick) else Modifier)
50-
.semantics { this.contentDescription = contentDescription }
5150
.size(48.dp)
5251
.aspectRatio(1f)
53-
.border(1.dp, strokeColor, CircleShape)
5452
.clip(CircleShape)
53+
.border(1.dp, strokeColor, CircleShape)
54+
.clickable(enabled = enabled, onClick = onClick, role = Role.Button)
5555
.background(KotlinConfTheme.colors.mainBackground),
5656
contentAlignment = Alignment.Center,
5757
) {
5858
Icon(
5959
painter = painterResource(icon),
60-
contentDescription = null,
60+
contentDescription = contentDescription,
6161
tint = iconColor,
6262
modifier = Modifier.size(24.dp)
6363
)
@@ -72,7 +72,7 @@ fun IconButtonPreviewEnabled() {
7272
icon = UiRes.drawable.bookmark_24,
7373
enabled = true,
7474
onClick = {},
75-
contentDescription = "",
75+
contentDescription = "Bookmark",
7676
)
7777
}
7878
}
@@ -85,7 +85,7 @@ fun IconButtonPreviewDisabled() {
8585
icon = UiRes.drawable.bookmark_24,
8686
enabled = false,
8787
onClick = {},
88-
contentDescription = "",
88+
contentDescription = "Bookmark",
8989
)
9090
}
9191
}

0 commit comments

Comments
 (0)