Repository navigation
Conversation
Code Coverage
Files
|
| val groupingSize = if (decimalFormat != null && decimalFormat.isGroupingUsed) { | ||
| decimalFormat.groupingSize | ||
| } else { | ||
| 3 |
There was a problem hiding this comment.
When the locale does not use grouping we fall back to 3, so we would still group the digits. The KDoc says <= 0 disables grouping, so shouldn't we return 0 here?
| 3 | |
| 0 |
| override val unitSystem: UnitSystem = UnitSystem.METRIC | ||
|
|
||
| override fun toDistanceUnits(meters: Meters): ValueWithUnitsTemplate = | ||
| if (abs(meters.value) < KILOMETERS_THRESHOLD.value) { |
There was a problem hiding this comment.
There is an edge case right below the threshold: 999.6 m stays in the meters branch but rounds up when formatted, so we get "1,000 m" instead of "1.0 km" (same for 1,319.6 ft, which shows as "1,320 ft" instead of "0.3 mi"). We already handle this for the 10 km/mi switch with isUnderTenAtOneDecimal. Could we compare the rounded value here too, and add a test near the threshold?
| Distance or elevation in feet, formatted to 0 decimal places. | ||
| For example, 1234.56 feet will be formatted as "1,235 ft". | ||
| --> | ||
| <string name="amu_in_feet" translatable="false">%1$,.0f ft</string> |
There was a problem hiding this comment.
Just to understand it: since all the templates are translatable="false", the Resources overloads produce the same output as the pure Kotlin path (formatWithTemplate), and we end up with two code paths to keep in sync. Should we either make the unit labels translatable, or drop the Resources overloads and the resource IDs from the public API?
| */ | ||
| public object ImperialUnitsConverter : UnitsConverter() { | ||
| /** Threshold (`0.25` miles = `1,320` feet) at which imperial distances switch from feet to miles. */ | ||
| public val MILES_THRESHOLD: Meters = 0.25.miles |
There was a problem hiding this comment.
Since Meters is a value class, the getter gets mangled (getMILES_THRESHOLD-NA-LpbA in library.api) and can't be called from Java. Could we add @get:JvmName here and on KILOMETERS_THRESHOLD, or expose them as Double constants?
|
|
||
| /** Shorthand to create a [Meters] measurement from a [Number] of meters. */ | ||
| @get:JvmName("m") | ||
| public inline val Number.m: Meters |
There was a problem hiding this comment.
I wonder if we could drop the short aliases (m, ft, mi, km). Being these extensions on Number in our root package, anyone importing them gets 5.m in autocompletion, and m is quite likely to clash with other libraries. The long forms read well enough, what do you think?
|
|
||
| /** Returns the equivalent number of international feet for this [Meters] measurement. */ | ||
| @get:JvmName("toFeet") | ||
| public inline val Meters.toFeet: Double |
There was a problem hiding this comment.
nit: in Kotlin to* names are usually functions, so meters.toFeet reads a bit like it is missing the (). What about inFeet / inMiles / inKilometers, similar to how Duration exposes its values?
| * and elevations: United States (`"US"`), Liberia (`"LR"`), Myanmar (`"MM"`), and | ||
| * United Kingdom (`"GB"`). | ||
| */ | ||
| public val IMPERIAL_COUNTRY_CODES: Set<String> = setOf("US", "LR", "MM", "GB") |
There was a problem hiding this comment.
Out of curiosity, is GB meant to apply to elevations too? In the UK road distances are in miles, but elevations (e.g. Ordnance Survey maps) are in meters, so "14,440 ft" may look odd there. Not a blocker, but maybe worth documenting, or splitting the distance and elevation systems later.
…nits
- Default `groupingSize` to `0` in `NumberFormatSymbols.fromLocale` when `!decimalFormat.isGroupingUsed`
- Fix threshold boundary rounding in `MetricUnitsConverter` (`999.6 m` -> `"1.0 km"`) and `ImperialUnitsConverter` (`1,319.6 ft` -> `"0.3 mi"`)
- Replace `translatable="false"` numeric templates with 4 translatable `%1$s` unit templates (`amu_in_feet`, `amu_in_miles`, `amu_in_meters`, `amu_in_kilometers`), add 24 localized `values-<locale>/strings.xml` translations, and unify `Locale` and `Resources` formatting onto a single `NumberFormatSymbols` code path
- Add `@get:JvmName("getMilesThreshold")` and `@get:JvmName("getKilometersThreshold")` for Java interop
- Remove short `Number.m`, `.km`, `.ft`, and `.mi` extensions and rename `Meters.to*` properties to `inMeters`, `inKilometers`, `inFeet`, and `inMiles`
- Default `"GB"` (`Locale.UK`) out-of-the-box to Imperial road distances (`ft`/`mi`) + Metric elevations (`m`), and add `withDistanceUnits`, `withElevationUnits`, `withDistanceConverter`, `withElevationConverter`, `withDistanceFormatter`, `withElevationFormatter`, and `UnitsConverter(...)` / `UnitsConverter.create(...)` overloads
- Update `README.md`, `llm-integration-prompt.md`, `.gemini/skills/android-maps-utils/SKILL.md`, and unit tests (`UnitsTest`, `UnitsJavaTest`, `UnitsDemoTest`)
|
I am seeking to have a good general purpose distance / elevation formatting tool that we can use in the scale bar fix. |
Summary
Adds a public
UnitsAPI (com.google.maps.android) to:libraryfor type-safe distance and elevation representation, framework-agnostic unit system resolution, and KMP-compatible logical precision formatting.Key Additions
METERS_PER_FOOT = 0.3048,FEET_PER_METER = 1.0 / METERS_PER_FOOT) and statute mile (FEET_PER_MILE = 5_280,METERS_PER_MILE = 1609.344,MILES_PER_METER) constants alongsideMETERS_PER_KILOMETER = 1_000.MetersInline Value Class:@JvmInline value class Meters(val value: Double) : Comparable<Meters>with+,-,*,/, unary-,Numberconstruction extensions (.meters/.m,.kilometers/.km,.feet/.ft,.miles/.mi), and scalar conversions (.toMeters,.toKilometers,.toFeet,.toMiles).UnitSystem&NumberFormatSymbols:UnitSystem.METRICandUnitSystem.IMPERIALwithfromLocale(locale = Locale.getDefault())andfromCountryCode(countryCode)defaulting"US","LR","MM", and"GB"toIMPERIALand all others toMETRIC.NumberFormatSymbolsfor KMP-friendly locale grouping and decimal separator resolution without relying onjava.util.Formatter(String.format).UnitsConverter,MetricUnitsConverter,ImperialUnitsConverter):fttomiat0.25miles (1,320feet) and frommtokmat1,000meters (1.0km).mbelow1 km,ftbelow0.25 mi, and all elevations) as whole integers (0decimals, with locale thousands grouping, e.g.,"450 m","528 ft","14,440 ft").0.25to< 10mi,1.0to< 10km) with1decimal digit, keeping the trailing.0(e.g.,"0.3 mi","1.0 km","2.0 km","2.5 mi").>= 10km or>= 10mi) as whole integers (0decimals, e.g.,"10 km","12 mi").Locale/NumberFormatSymbols) and AndroidResourcesformatting (amu_in_*), plusDoubleoverloads for Java callers.UnitsDemoActivity(Kotlin + Compose + GoogleMap) and updatedDistanceDemoActivity(Java).UnitsTestandUnitsDemoTest.Test Plan
./gradlew apiCheck spotlessCheck :library:testDebugUnitTest :demo:testStandardDebugUnitTest :library:lintDebugUnitsDemoActivityandDistanceDemoActivityon emulator (emulator-5554) and Pixel 6.