使用区域设置来检测是否使用英制单位

发布于 2024-10-15 21:33:04 字数 177 浏览 7 评论 0原文

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

美国、利比里亚和缅甸应该使用英制单位,而世界其他地区则使用正常单位。一种方法是将此逻辑放入我自己的类中,但我更喜欢使用任何单位。内置逻辑(如果可用)?

I'm working on an app that wants to display lengths either in centimeters (cm) or in inches("). Is there a way to select the right unit from the locale? In any event I'm also going to put in an option so that the user can to override the locale setting.

USA, Liberia, and Burma should use imperial units and the rest of the world normal units. One way is to put in this logic in my own classes, but I would prefer using any built in logic if available. Any pointers?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

无所谓啦 2024-10-22 21:33:04

最后我采用了以下解决方案。

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 对象上使用 int 的性能提升极其有限,并且使代码更难以阅读。在 java 中比较两个引用在速度上与比较两个int相当。使用对象还允许我们向 UnitLocale 类或子类添加方法,例如,convertToMetric 等。

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

In the end I went for the following solution.

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;
    }
}

Use it like this for example.

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

If convert methods are also need they can preferably be added to subclasses of UnitLocale. I only needed to detect wheter to use imperial units and send it to the server.

Using ints over java objects have extremely slim performance gains and makes the code harder to read. Comparing two references in java is comparable in speed to comparing two ints. Also using objects allow us to add methods to the UnitLocale class or subclasses such as, convertToMetric, etc.

You could also use an enum instead if you prefer that.

早乙女 2024-10-22 21:33:04

LocaleData.getMeasurementSystem 是从 API 级别 28 及更高版本可用。它返回您正在寻找的信息。

LocaleData.getMeasurementSystem is available from API level 28 and beyond. It returns the information you are looking for.

木緿 2024-10-22 21:33:04

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

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
    }

请注意,英国和美国的英制系统之间存在差异,请参阅 wiki 文章了解更多详细信息。

A more or less complete way to do this is this way.

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
    }

Note that there is a difference between UK and US imperial systems, see the wiki articles for more details.

聆听风音 2024-10-22 21:33:04

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

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

这样,您需要做的就是调用:

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

Building on the other nice solutions here, you can also implement this as a Kotlin extension function to the Locale object:

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

This way, all you need to do is call:

val metric = Locale.getDefault().isMetric()
述情 2024-10-22 21:33:04
  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。然后从代码中读取该布尔资源。

  1. Programmatically

Making a small improvement in the solution from @vidstige

I would use getCountry().toUpperCase() to be safe and change the checks to a switch for a cleaner code. Something like this:

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. From Resources

Another solution could be creating resources folders for each country like: [values_US] [values_LR] [values_MM] with a boolean resource changed to true. Then read that boolean resource from the code.

风苍溪 2024-10-22 21:33:04

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

Just give the user the option to choose a preferred unit in a settings menu. If it is a traveling user you don't want the app to be geographically aware, IMO.

昔梦 2024-10-22 21:33:04

java中可用的测量单位(英国、美国、国际单位制) LocaleData

用于

LocaleData.getMeasurementSystem(ULocale.getDefault()) 

获取根据设备区域设置使用的精确测量单位

// kotlin code
val unit  = LocaleData.getMeasurementSystem(ULocale.getDefault())
            
      when(unit)
      {
          MeasurementSystem.SI -> Log.d("length1", "SI")
          MeasurementSystem.US -> Log.d("length1", "US")
          MeasurementSystem.UK -> Log.d("length1", "UK")
       } 

,其中

  • SI:英制系统(除英国、美国、缅甸、利比里亚之外的所有地方)

  • UK:帝国和美国(英国)的混合

  • 美国:公制(用于美国、利比里亚、缅甸)

Measurement (UK, US, SI) Unit available in java LocaleData

use

LocaleData.getMeasurementSystem(ULocale.getDefault()) 

to get exact measurement units used according to device locale

// kotlin code
val unit  = LocaleData.getMeasurementSystem(ULocale.getDefault())
            
      when(unit)
      {
          MeasurementSystem.SI -> Log.d("length1", "SI")
          MeasurementSystem.US -> Log.d("length1", "US")
          MeasurementSystem.UK -> Log.d("length1", "UK")
       } 

where

  • SI : Imperial system (every where except UK, US, Myanmar, Liberia)

  • UK : mix of imperial and US (UK)

  • US : metric system (used in US, Liberia, Myanmar)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文