Использование настроек локали для определения, использовать ли имперские единицы - PullRequest
24 голосов
/ 04 февраля 2011

Я работаю над приложением, которое хочет отображать длины в сантиметрах (см) или в дюймах ("). Есть ли способ выбрать правильную единицу измерения из локали? В любом случае я также собираюсьвключите опцию, чтобы пользователь мог переопределить настройку локали.

США, Либерия и Бирма должны использовать имперские единицы и нормальные единицы остального мира. Один из способов - вставить эту логику в мойсобственные классы, но я бы предпочел использовать любую встроенную логику, если она доступна. Любые указатели?

Ответы [ 5 ]

46 голосов
/ 22 октября 2011

В конце концов я выбрал следующее решение.

public class UnitLocale {
    public static UnitLocale Imperial = new UnitLocale();
    public static UnitLocale Metric = new UnitLocale();

    public static UnitLocale getDefault() {
            return getFrom(Locale.getDefault());
    }
    public static UnitLocale getFrom(Locale locale) {
        String countryCode = locale.getCountry();
        if ("US".equals(countryCode)) return Imperial; // USA
        if ("LR".equals(countryCode)) return Imperial; // Liberia
        if ("MM".equals(countryCode)) return Imperial; // Myanmar
        return Metric;
    }
}

Используйте его, например, следующим образом.

if (UnitLocale.getDefault() == UnitLocale.Imperial) convertToimperial();

Если методы преобразования также необходимы, их предпочтительно добавить вподклассы UnitLocale.Мне нужно было только обнаружить , чтобы использовать имперские единицы и отправить его на сервер.

Использование int s над объектами java значительно снижает производительность и затрудняет чтение кода.Сравнение двух ссылок в Java сопоставимо по скорости с сопоставлением двух ints.Кроме того, использование объектов позволяет нам добавлять методы к классу или подклассам UnitLocale, таким как, convertToMetric и т. Д.

Вместо этого вы также можете использовать enum, если хотите.

3 голосов
/ 22 ноября 2016
  1. Программно

Небольшое улучшение решения от @ vidstige

Я бы использовал getCountry (). ToUpperCase () для обеспечения безопасности и изменил бы проверки напереключатель для более чистого кода.Как то так:

public static UnitLocale getFrom(Locale locale) {
    String countryCode = locale.getCountry().toUpperCase();
    switch (countryCode) {
        case "US":
        case "LR":
        case "MM":
            return Imperial;
        default:
            return Metric;
    }
}
Из ресурсов

Другим решением может быть создание папок ресурсов для каждой страны, например: [values_US] [values_LR] [values_MM] с логическим ресурсом, измененным на true.Затем прочитайте этот логический ресурс из кода.

2 голосов
/ 10 апреля 2019

Основываясь на других хороших решениях, вы также можете реализовать это как функцию расширения Kotlin для объекта Locale:

fun Locale.isMetric(): Boolean {
    return when (country.toUpperCase()) {
        "US", "LR", "MM" -> false
        else -> true
    }
}

Таким образом, все, что вам нужно сделать, это позвонить:

val metric = Locale.getDefault().isMetric()
2 голосов
/ 06 ноября 2018

Более или менее полный способ сделать это следующим образом.

Kotlin:

private fun Locale.toUnitSystem() =
    when (country.toUpperCase()) {
        // https://en.wikipedia.org/wiki/United_States_customary_units
        // https://en.wikipedia.org/wiki/Imperial_units
        "US" -> UnitSystem.IMPERIAL_US
        // UK, Myanmar, Liberia, 
        "GB", "MM", "LR" -> UnitSystem.IMPERIAL
        else -> UnitSystem.METRIC
    }

Примечание , что естьРазница между британскими и американскими имперскими системами, см. вики-статьи для более подробной информации.

2 голосов
/ 04 февраля 2011

Просто дайте пользователю возможность выбрать предпочтительный блок в меню настроек.Если вы путешествуете, вы не хотите, чтобы приложение было географически осведомлено, IMO.

...