Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: init with padding with static context to avoid @Composable requirement #43

Merged
merged 3 commits into from
Sep 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,25 @@ import android.view.Gravity
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import com.mapbox.mapboxsdk.geometry.LatLng
import com.maplibre.compose.MapView
import com.maplibre.compose.camera.MapViewCamera
import com.maplibre.compose.rememberSaveableMapViewCamera
import com.maplibre.compose.runtime.localLayoutDirection
import com.maplibre.compose.settings.AttributionSettings
import com.maplibre.compose.settings.CompassSettings
import com.maplibre.compose.settings.LogoSettings
import com.maplibre.compose.settings.MapControlPosition
import com.maplibre.compose.settings.MapControls
import com.maplibre.compose.settings.MarginInsets
import com.maplibre.compose.symbols.Polyline
import kotlinx.coroutines.delay

/**
* MapControls modify the UiSettings for controls on the map including the compass, logo, and
Expand All @@ -23,28 +31,64 @@ import com.maplibre.compose.settings.MarginInsets
@Composable
fun MapControlsExample() {

val density = LocalDensity.current
val layoutDirection = localLayoutDirection()

// Create an initial set of map controls
val initialMapControls =
MapControls(
attribution =
AttributionSettings.initWithPosition(
position = MapControlPosition.TopEnd(horizontal = 64.dp, vertical = 64.dp)),
compass =
// Using margins directly is possible, but it's better to use
// [MapControlPosition] as seen above in with AttributionSettings
CompassSettings(
fadeFacingNorth = false,
gravity = Gravity.START or Gravity.BOTTOM,
margins =
MarginInsets.createFromPadding(PaddingValues(start = 64.dp, bottom = 128.dp)),
),
logo = LogoSettings(enabled = false))

// Remember the map controls and color as mutable state to update them in the LaunchedEffect.
val mapControls = remember { mutableStateOf(initialMapControls) }
val color = remember { mutableStateOf("#000") }

// Dynamically update the map controls and polyline after a delay
LaunchedEffect(Unit) {
delay(2000)

mapControls.value =
MapControls(
attribution =
AttributionSettings.initWithLayoutAndPosition(
layoutDirection = layoutDirection,
density = density,
enabled = true,
position = MapControlPosition.TopCenter(vertical = 64.dp)),
compass = CompassSettings(enabled = false),
logo = LogoSettings(enabled = true))

color.value = "#fff"
}

val mapViewCamera =
rememberSaveableMapViewCamera(
initialCamera = MapViewCamera.Centered(latitude = -50.04, longitude = -73.71, zoom = 7.0))

val latLngs =
listOf(
LatLng(-50.20, -73.69),
LatLng(-50.10, -73.71),
LatLng(-50.00, -73.73),
)

MapView(
modifier = Modifier.fillMaxSize(),
styleUrl = "https://demotiles.maplibre.org/style.json",
camera = mapViewCamera,
mapControls =
MapControls(
attribution =
AttributionSettings.initWithPosition(
position = MapControlPosition.TopEnd(horizontal = 64.dp, vertical = 64.dp)),
compass =
// Using margins directly is possible, but it's better to use
// [MapControlPosition] as seen above in with AttributionSettings
CompassSettings(
fadeFacingNorth = false,
gravity = Gravity.START or Gravity.BOTTOM,
margins =
MarginInsets.createFromPadding(
PaddingValues(start = 64.dp, bottom = 128.dp)),
),
logo = LogoSettings(enabled = false)))
mapControls = mapControls.value) {
Polyline(points = latLngs, color = color.value, lineWidth = 12f)
}
}
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ plugins {
}

allprojects {
version = "0.0.17"
version = "0.0.18"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.maplibre.compose.runtime

import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.unit.LayoutDirection

/**
* Get the layout direction of the screen as a [LayoutDirection].
*
* @return The current layout direction of the screen.
*/
@Composable
fun localLayoutDirection(): LayoutDirection {
val direction = LocalConfiguration.current.layoutDirection
return LayoutDirection.entries[direction]
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package com.maplibre.compose.settings

import android.os.Parcelable
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection
import com.maplibre.compose.runtime.localLayoutDirection
import kotlinx.parcelize.Parcelize

/**
Expand All @@ -22,12 +26,45 @@ data class AttributionSettings(
) : Parcelable {

companion object {

/**
* Configure the attribution view.
*
* @param enabled Whether the attribution view is enabled.
* @param position The position of the attribution view.
* @param tintColor The tint color of the attribution view.
* @return The attribution settings.
*/
@Composable
fun initWithPosition(
enabled: Boolean? = null,
position: MapControlPosition = MapControlPosition.TopStart(),
tintColor: Int? = null
): AttributionSettings =
AttributionSettings(enabled, position.asGravity(), position.asMarginInsets(), tintColor)
initWithLayoutAndPosition(
localLayoutDirection(), LocalDensity.current, enabled, position, tintColor)

/**
* Configure the attribution view.
*
* @param layoutDirection The layout direction of the screen.
* @param density The layout density (e.g. [LocalDensity.current]).
* @param enabled Whether the attribution view is enabled.
* @param position The position of the attribution view.
* @param tintColor The tint color of the attribution view.
* @return The attribution settings.
*/
fun initWithLayoutAndPosition(
layoutDirection: LayoutDirection,
density: Density,
enabled: Boolean? = null,
position: MapControlPosition = MapControlPosition.TopStart(),
tintColor: Int? = null
): AttributionSettings =
AttributionSettings(
enabled,
position.asGravity(),
position.asMarginInsets(layoutDirection, density),
tintColor)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package com.maplibre.compose.settings

import android.os.Parcelable
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection
import com.maplibre.compose.runtime.localLayoutDirection
import kotlinx.parcelize.Parcelize

/**
Expand Down Expand Up @@ -36,6 +40,30 @@ data class CompassSettings(
isFacingNorth: Boolean? = null,
position: MapControlPosition = MapControlPosition.TopStart()
): CompassSettings =
CompassSettings(enabled, isFacingNorth, position.asGravity(), position.asMarginInsets())
initWithLayoutAndPosition(
localLayoutDirection(), LocalDensity.current, enabled, isFacingNorth, position)

/**
* Configure the compass.
*
* @param layoutDirection The layout direction of the screen.
* @param density The layout density (e.g. [LocalDensity.current]).
* @param enabled Whether the compass is enabled.
* @param isFacingNorth
* @param position The position of the compass.
* @return The compass settings.
*/
fun initWithLayoutAndPosition(
layoutDirection: LayoutDirection,
density: Density,
enabled: Boolean? = null,
isFacingNorth: Boolean? = null,
position: MapControlPosition = MapControlPosition.TopStart()
): CompassSettings =
CompassSettings(
enabled,
isFacingNorth,
position.asGravity(),
position.asMarginInsets(layoutDirection, density))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package com.maplibre.compose.settings

import android.os.Parcelable
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection
import com.maplibre.compose.runtime.localLayoutDirection
import kotlinx.parcelize.Parcelize

/**
Expand Down Expand Up @@ -33,6 +37,28 @@ data class LogoSettings(
fun initWithPosition(
enabled: Boolean? = null,
position: MapControlPosition = MapControlPosition.TopStart()
): LogoSettings = LogoSettings(enabled, position.asGravity(), position.asMarginInsets())
): LogoSettings =
LogoSettings(
enabled,
position.asGravity(),
position.asMarginInsets(localLayoutDirection(), LocalDensity.current))

/**
* Configure the logo.
*
* @param layoutDirection The layout direction of the logo.
* @param density The density of the logo.
* @param enabled Whether the logo is enabled.
* @param position The position of the logo.
* @return The logo settings.
*/
fun initWithLayoutAndPosition(
layoutDirection: LayoutDirection,
density: Density,
enabled: Boolean? = null,
position: MapControlPosition = MapControlPosition.TopStart()
): LogoSettings =
LogoSettings(
enabled, position.asGravity(), position.asMarginInsets(layoutDirection, density))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import com.maplibre.compose.runtime.localLayoutDirection
import kotlinx.parcelize.Parcelize

sealed class MapControlPosition(open val horizontal: Dp = 0.dp, open val vertical: Dp = 0.dp) {
Expand Down Expand Up @@ -100,9 +101,10 @@ sealed class MapControlPosition(open val horizontal: Dp = 0.dp, open val vertica
}
}

@Composable
internal fun asMarginInsets(): MarginInsets {
return MarginInsets.createFromPadding(
internal fun asMarginInsets(layoutDirection: LayoutDirection, density: Density): MarginInsets {
return MarginInsets.createFromLayoutAndPadding(
layoutDirection = layoutDirection,
density = density,
padding =
PaddingValues(start = horizontal, top = vertical, end = horizontal, bottom = vertical))
}
Expand Down Expand Up @@ -139,11 +141,27 @@ data class MarginInsets(
*/
@Composable
fun createFromPadding(padding: PaddingValues): MarginInsets {
val rawLayoutDirection = LocalConfiguration.current.layoutDirection
val layoutDirection: LayoutDirection = LayoutDirection.entries[rawLayoutDirection]

val density = LocalDensity.current
return createFromLayoutAndPadding(
layoutDirection = localLayoutDirection(),
density = LocalDensity.current,
padding = padding)
}

/**
* Manually position the control on the map using dp padding, a layout direction, and a density.
*
* To more easily position the control on a map use the control's `initWithPosition` and
* [MapControlPosition] as it safely handles the nuances of map control positioning.
*
* @param layoutDirection The layout direction to use
* @param density The screen density to use (e.g. LocalDensity.current).
* @param padding The padding values to use.
*/
fun createFromLayoutAndPadding(
layoutDirection: LayoutDirection,
density: Density,
padding: PaddingValues
): MarginInsets {
val start = padding.calculateStartPadding(layoutDirection)
val top = padding.calculateTopPadding()
val end = padding.calculateEndPadding(layoutDirection)
Expand Down