web-dev-qa-db-ja.com

ロケール設定を使用して、インペリアル単位を使用するかどうかを検出する

長さをセンチメートル(cm)またはインチ( ")で表示したいアプリに取り組んでいます。ロケールから適切な単位を選択する方法はありますか?いずれにしても、ユーザーがロケール設定を上書きできるようにするオプション。

米国、リベリア、ビルマは、帝国単位とその他の世界の通常の単位を使用する必要があります。 1つの方法は、このロジックを自分のクラスに配置することですが、可能な場合は、組み込みロジックを使用することをお勧めします。ポインタはありますか?

28
vidstige

結局、私は次の解決策に行きました。

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の2つの参照を比較すると、速度は同等です。 2つのintsを比較します。また、オブジェクトを使用すると、UnitLocaleクラスまたはconvertToMetricなどのサブクラスにメソッドを追加できます。

必要に応じて、代わりに列挙型を使用することもできます。

46
vidstige

これを行うための多かれ少なかれ完全な方法はこの方法です。

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の記事を参照してください。

3
joecks
  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. リソースから

別の解決策は、ブール値のリソースをtrueに変更した[values_US] [values_LR] [values_MM]のような国ごとのリソースフォルダーを作成することです。次に、そのブールリソースをコードから読み取ります。

3
Benny

設定メニューで好みの単位を選択するオプションをユーザーに与えるだけです。旅行中のユーザーの場合、アプリに地理的な認識を持たせたくない、IMO。

2
AndroidHustle

ここにある他のNiceソリューションに基づいて、これをLocaleオブジェクトのKotlin拡張関数として実装することもできます。

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

このように、あなたがする必要があるのは電話することだけです:

val metric = Locale.getDefault().isMetric()
2
Russell Stewart