【问题标题】:Using locale settings to detect wheter to use imperial units使用区域设置来检测是否使用英制单位
【发布时间】:2011-06-21 08:36:57
【问题描述】:

我正在开发一个应用程序,它希望以厘米 (cm) 或英寸 (") 为单位显示长度。有没有办法从区域设置中选择正确的单位?无论如何我也会放入一个选项,以便用户可以覆盖区域设置。

美国、利比里亚和缅甸应使用英制单位和世界其他地区的标准单位。一种方法是将此逻辑放入我自己的类中,但如果可用,我更喜欢使用任何内置逻辑。有什么指点吗?

【问题讨论】:

  • “美国、利比里亚和缅甸应该使用英制单位”好吧,这值得商榷。
  • @endolith 是的 :) 如此真实。但是虽然世界是这样的......
  • 仅供参考,英制单位与美国单位不同。例如,英制加仑比美制加仑大 16%,英制磅比美制磅大 21%。
  • 从 API 级别 28 开始,Android 框架为此提供了官方 API。请阅读下面的回复。

标签: android localization internationalization units-of-measurement


【解决方案1】:

最后我选择了以下解决方案。

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 的子类中。我只需要检测是否使用英制单位并将其发送到服务器。

在 java 对象上使用ints 的性能提升非常小,并且使代码更难阅读。在 java 中比较两个引用的速度与比较两个 ints 的速度相当。同样使用对象允许我们向UnitLocale 类或子类(例如convertToMetric 等)添加方法。

如果您愿意,也可以使用枚举来代替。

【讨论】:

  • 不错的解决方案@。我只是将其更改为使用 enum :) 所以我可以在我已经拥有的实用程序类中使用它来进行单位转换。
  • @MarcinOrlowski 感谢您的支持,但是 int 有什么意义?
  • 不错的答案!只有这 3 个国家是帝国的依据是什么?
  • 谢谢!真的很难说,但在我看来,这主要是保留帝国制度的历史和政治原因。
  • 从 API 级别 28 开始,Android 框架为此提供了官方 API。请阅读下面的回复。
【解决方案2】:

一个或多或少完整的方法就是这样。

科特林:

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
    }

请注意英制和美制之间存在差异,有关详细信息,请参阅 wiki 文章。

【讨论】:

【解决方案3】:

在此处其他不错的解决方案的基础上,您还可以将其实现为 Locale 对象的 Kotlin 扩展函数:

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

这样,你只需调用:

val metric = Locale.getDefault().isMetric()

【讨论】:

  • 好吧,这里没有英国。
【解决方案4】:

LocaleData.getMeasurementSystem 可从 API 级别 28 及更高级别获得。它返回您正在查找的信息。

【讨论】:

  • 太棒了! ?
【解决方案5】:
  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;
    }
}
  1. 来自资源

另一种解决方案是为每个国家/地区创建资源文件夹,例如:[values_US] [values_LR] [values_MM] 将布尔资源更改为 true。然后从代码中读取该布尔资源。

【讨论】:

  • 什么时候需要toUpperCase()?它是未使用的代码,应该被删除。如何清洁开关盒?这只是更多的代码行和更混乱的 reda。
  • 嗨,我们知道讨论不同的编码风格。我相信一个 switch 实际上比几个 if else 语句更有效。
  • 关于toUpperCase(),我知道它看起来很多余,但是Android设备制造商可以修改源代码,你永远不知道国家代码是否总是大写。这是一个品味问题。
  • 是的,能够激发您的编码风格非常重要。如果你这样做toUpperCase(),你会在哪里停下来?制造商还可以添加前缀和后缀。也许您还应该修剪空白?
【解决方案6】:

只需让用户在设置菜单中选择首选单位即可。如果是旅行用户,您不希望应用具有地理感知能力,IMO。

【讨论】:

  • 好点。将其作为一个选项总是比为我选择它更好。
  • 好点。无论如何我都会设置一个。但是,语言环境取决于用户而不是位置。也就是说,来自美国的用户总是希望看到英寸,无论她在哪里旅行。因此,一个不错的默认选择会很方便。
  • 旅行与地区无关。美国人无需旅行即可选择 LR 或 MM 地区。
  • 就我而言,我确实有设置单位的设置,但我想使用此自动检测来设置默认值。
  • @Corbella 的方法是解决这个问题的正确方法 - 然后大多数用户可以在不更改任何内容的情况下拿起并使用该应用程序,但如果他们需要,这种能力就在那里。
猜你喜欢
  • 1970-01-01
  • 2010-11-08
  • 2021-03-04
  • 2020-11-21
  • 1970-01-01
  • 1970-01-01
  • 2020-06-29
  • 1970-01-01
  • 2010-12-01
相关资源
最近更新 更多