2013-09-25 35 views
42

Có cách nào để xác định ngôn ngữ RTL (từ phải sang trái), ngoài việc kiểm tra mã ngôn ngữ đối với tất cả ngôn ngữ RTL?Xác định ngôn ngữ RTL trong Android

Kể từ API 17+ cho phép nhiều nguồn lực cho RTL và LTR, tôi giả sử, cần có một cách, ít nhất là từ API 17.

Trả lời

51

lấy nó từ Configuration.getLayoutDirection():

Configuration config = getResources().getConfiguration(); 
if(config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) { 
    //in Right To Left layout 
} 
+2

Thật không may "thêm ở mức API 17" để nó sẽ không hoạt động trên các phiên bản cũ hơn. – EvZ

+3

Giải pháp này hoạt động khi bạn sử dụng "Hướng bố cục lực RTL" trong tùy chọn nhà phát triển! –

+1

Đó là cách bạn có thể làm điều đó cho các cấp API dưới 17: http://stackoverflow.com/a/28568974/170842. – Michael

0

Native RTL support in Android 4.2

public static ComponentOrientation getOrientation(Locale locale) 
    { 
      // A more flexible implementation would consult a ResourceBundle 
      // to find the appropriate orientation. Until pluggable locales 
      // are introduced however, the flexiblity isn't really needed. 
      // So we choose efficiency instead. 
      String lang = locale.getLanguage(); 
      if("iw".equals(lang) || "ar".equals(lang) 
       || "fa".equals(lang) || "ur".equals(lang)) 
      { 
       return RIGHT_TO_LEFT; 
      } else { 
       return LEFT_TO_RIGHT; 
      } 
    } 
+0

Tốt! Câu trả lời hoàn chỉnh hơn tại đây: http://stackoverflow.com/questions/20814564/how-to-find-out-locale-dependent-text-orientation-in-java#20821395 bạn sẽ cập nhật của bạn? – Pascal

3

Để kiểm soát chính xác hơn giao diện người dùng ứng dụng của bạn ở cả chế độ LTR và RTL, Android 4.2 bao gồm các API mới sau đây để giúp quản lý Xem thành phần:

android:layoutDirection — attribute for setting the direction of a component's layout. 
android:textDirection — attribute for setting the direction of a component's text. 
android:textAlignment — attribute for setting the alignment of a component's text. 
getLayoutDirectionFromLocale() — method for getting the Locale-specified direction 

Do đó getLayoutDirectionFromLocale() sẽ giúp bạn. Tham khảo mã mẫu tại đây: https://android.googlesource.com/platform/frameworks/base.git/+/3fb824bae3322252a68c1cf8537280a5d2bd356d/core/tests/coretests/src/android/util/LocaleUtilTest.java

2

Xin cảm ơn tất cả.

Nếu bạn nhìn vào mã số LayoutUtil.getLayoutDirectionFromLocale() (và, tôi giả sử Confuiguration.getLayoutDirection()), kết thúc bằng cách phân tích chữ cái bắt đầu của tên hiển thị ngôn ngữ, sử dụng Character.getDirectionality.

Kể từ Character.getDirectionality là khoảng từ Android 1, đoạn code sau sẽ tương thích với tất cả các phiên Android (ngay cả những người, không hỗ trợ RTL đúng :)):

public static boolean isRTL() { 
    return isRTL(Locale.getDefault()); 
} 

public static boolean isRTL(Locale locale) { 
    return 
     Character.getDirectionality(locale.getDisplayName().charAt(0)) == 
      Character.DIRECTIONALITY_RIGHT_TO_LEFT; 
} 
1

này sẽ làm việc trong tất cả các SDK:

private boolean isRTL() { 
    Locale defLocale = Locale.getDefault(); 
    return Character.getDirectionality(defLocale.getDisplayName(defLocale).charAt(0)) == Character.DIRECTIONALITY_RIGHT_TO_LEFT; 
} 
45

câu trả lời của @ cyanide có cách tiếp cận đúng nhưng là một lỗi nghiêm trọng.

Character.getDirectionality trả về Bi-directional (bidi) character type. Văn bản từ trái sang phải là loại có thể dự đoán L và từ phải sang trái cũng có thể được dự đoán là loại R. NHƯNG, văn bản Ả Rập trả về một loại khác, gõ AL.

Tôi đã thêm séc cho cả loại R và loại AL và sau đó kiểm tra thủ công mọi ngôn ngữ RTL Android đi kèm: tiếng Hebrew (Israel), tiếng Ả Rập (Ai Cập) và tiếng Ả Rập (Israel).

Như bạn có thể thấy, điều này bỏ qua các ngôn ngữ từ phải sang trái khác, vì vậy tôi lo ngại rằng Android thêm các ngôn ngữ này, có thể có vấn đề tương tự và có thể không nhận thấy ngay lập tức.

Vì vậy, tôi đã thử nghiệm thủ công từng ngôn ngữ RTL.

  • Arabic (العربية) = gõ AL
  • Kurd (کوردی) = gõ AL
  • Farsi (فارسی) = gõ AL
  • Urdu (اردو) = gõ AL
  • Hebrew (עברית) = loại R
  • Yiddish (ייִדיש) = loại R

Vì vậy, nó trông như thế này nên làm việc grea t:

public static boolean isRTL() { 
    return isRTL(Locale.getDefault()); 
} 

public static boolean isRTL(Locale locale) { 
    final int directionality = Character.getDirectionality(locale.getDisplayName().charAt(0)); 
    return directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT || 
      directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC; 
} 

Cảm ơn @cyanide đã gửi cho tôi đúng hướng!

+2

Điều này gây ra một 'StringIndexOutOfBoundsException' từ' locale.getDisplayName(). CharAt (0) '. Dường như đây là [vấn đề đã biết] (https://bugs.openjdk.java.net/browse/JDK-6992272?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab) với Java 7. Giải pháp hiện tại của tôi xung quanh đây là một cái gì đó giống như 'final String language = application.getResources(). getConfiguration(). locale.getLanguage(); ' ' return Strings.equals (ngôn ngữ, "iw") || Strings.equals (ngôn ngữ, "ar") || Strings.equals (language, "he"); ' – seato

+0

@seato thú vị ... là cái gì đó ảnh hưởng đến các thiết bị Android thực hay chỉ là các môi trường thử nghiệm như Genymotion? –

+0

@TimTrueman Nó ảnh hưởng đến các thiết bị Android thực. – seato

16

Nếu bạn đang sử dụng các thư viện hỗ trợ, bạn có thể làm như sau:

if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL) { 
    // The view has RTL layout 
} else { 
    // The view has LTR layout 
} 
+0

Tôi cần thay đổi bố cục theo địa phương của họ. Tôi có thể thay đổi dây. nhưng tôi không thể thay đổi hình ảnh. giả sử trong hình ảnh tiếng anh là ở phía bên trái khi tôi thay đổi sang tiếng Ả Rập nó phải là right.I cần phải thay đổi trên nút bấm. nếu tôi đi cài đặt> ngôn ngữ. của nó woking tốt. nhưng trong mã nó không hoạt động. Tôi chỉ tạo một bố cục. làm ơn cho tôi biết. –

+0

Chúng tôi có thể sử dụng điều này cho API trước 17 không? – DastakWall

8

tôi thu thập được nhiều thông tin và cuối cùng được thực hiện riêng, hy vọng hoàn tất, RTLUtils lớp học của tôi.

Nó cho phép biết nếu một Locale nhất định hoặc View là 'RTL' :-)

package com.elementique.shared.lang; 

import java.util.Collections; 
import java.util.HashSet; 
import java.util.Locale; 
import java.util.Set; 

import android.support.v4.view.ViewCompat; 
import android.view.View; 

public class RTLUtils 
{ 

    private static final Set<String> RTL; 

    static 
    { 
     Set<String> lang = new HashSet<String>(); 
     lang.add("ar"); // Arabic 
     lang.add("dv"); // Divehi 
     lang.add("fa"); // Persian (Farsi) 
     lang.add("ha"); // Hausa 
     lang.add("he"); // Hebrew 
     lang.add("iw"); // Hebrew (old code) 
     lang.add("ji"); // Yiddish (old code) 
     lang.add("ps"); // Pashto, Pushto 
     lang.add("ur"); // Urdu 
     lang.add("yi"); // Yiddish 
     RTL = Collections.unmodifiableSet(lang); 
    } 

    public static boolean isRTL(Locale locale) 
    { 
     if(locale == null) 
      return false; 

     // Character.getDirectionality(locale.getDisplayName().charAt(0)) 
     // can lead to NPE (Java 7 bug) 
     // https://bugs.openjdk.java.net/browse/JDK-6992272?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab 
     // using hard coded list of locale instead 
     return RTL.contains(locale.getLanguage()); 
    } 

    public static boolean isRTL(View view) 
    { 
     if(view == null) 
      return false; 

     // config.getLayoutDirection() only available since 4.2 
     // -> using ViewCompat instead (from Android support library) 
     if (ViewCompat.getLayoutDirection(view) == View.LAYOUT_DIRECTION_RTL) 
     { 
      return true; 
     } 
     return false; 
    } 
} 

Thưởng thức :-)

+0

Tôi cần thay đổi bố cục theo địa phương của họ. Tôi có thể thay đổi dây. nhưng tôi không thể thay đổi hình ảnh. giả sử trong hình ảnh tiếng anh là ở phía bên trái khi tôi thay đổi sang tiếng Ả Rập nó phải là right.I cần phải thay đổi trên nút bấm. nếu tôi đi cài đặt> ngôn ngữ. của nó woking tốt. nhưng trong mã nó không hoạt động. Tôi chỉ tạo một bố cục. làm ơn cho tôi biết. –

+0

@ Maid786 Không chắc chắn bạn muốn làm gì. Hãy xem https://developer.android.com/reference/android/widget/ImageView.html#onRtlPropertiesChanged(int) và http://stackoverflow.com/questions/9338447/android-flip-image-in-xml – Pascal

9

Có một cách thực sự đơn giản để kiểm tra theo hướng bố trí của một xem, nhưng nó quay trở lại LTR trên các thiết bị API 17 trước:

ViewUtils.isLayoutRtl(View view); 

lớp ViewUtils đi kèm với thư viện hỗ trợ v7, vì vậy nó phải là ava ilable nếu bạn đang sử dụng thư viện appcompat.

+0

Tôi cần thay đổi bố cục theo địa phương của họ. Tôi có thể thay đổi dây. nhưng tôi không thể thay đổi hình ảnh. giả sử trong hình ảnh tiếng anh là ở phía bên trái khi tôi thay đổi sang tiếng Ả Rập nó phải là right.I cần phải thay đổi trên nút bấm. nếu tôi đi cài đặt> ngôn ngữ. của nó woking tốt. nhưng trong mã nó không hoạt động. Tôi chỉ tạo một bố cục. làm ơn cho tôi biết. –

+0

Điều này chỉ gọi đến 'ViewCompat.getLayoutDirection (xem) == ViewCompat.LAYOUT_DIRECTION_RTL;', và chức năng này không có sẵn cho chúng ta sử dụng (IDE hiển thị lỗi khi sử dụng nó). –

0

Chỉ cần sử dụng mã này:

public static boolean isRTL() { 
    return isRTL(Locale.getDefault()); 
} 

public static boolean isRTL(Locale locale) { 
    final int directionality = Character.getDirectionality(locale.getDisplayName().charAt(0)); 
    return directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT || 
     directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC; 
} 

if (isRTL()) { 
    // The view has RTL layout 
} 
else { 
    // The view has LTR layout 
} 

này sẽ làm việc cho tất cả lavels API Android.

8

Bạn có thể sử dụng TextUtilsCompat từ thư viện hỗ trợ.

TextUtilsCompat.getLayoutDirectionFromLocale(locale)

+0

Sử dụng các thư viện compat luôn là một cách thông minh để đi nhưng đây là trường hợp mà Character.getDirectionality có sẵn tất cả các cách để API 1. Tôi sẽ nói cả hai đều được chấp nhận. – Elliott

+0

Lưu ý rằng nếu minSdk của bạn ít nhất là 17, bạn có thể sử dụng cuộc gọi thông thường thay vào đó: https://developer.android.com/reference/android/text/TextUtils.html#getLayoutDirectionFromLocale(java.util.Locale) –

2

Khi xây dựng thư viện bạn cũng luôn cần phải kiểm tra xem ứng dụng đang hỗ trợ RTL bằng cách sử dụng

(getApplicationInfo().flags &= ApplicationInfo.FLAG_SUPPORTS_RTL) != 0 

Khi ứng dụng đang chạy trên RTL miền địa phương, nhưng nó không được khai báo trong manifest android:supportsRtl="true" sau đó nó đang chạy trong chế độ LTR.

+0

Điểm tốt cho một thư viện! Tuy nhiên, trong ứng dụng chính tôi biết rằng supportRtl được thiết lập, vì vậy việc kiểm tra có vẻ không cần thiết. – cyanide

-1

Vì thiết bị tiếng Anh hỗ trợ RTL, bạn có thể sử dụng mã này trong MainActivity để thay đổi ngôn ngữ thiết bị sang tiếng Anh và bạn không cần phải "supportRTL" mã.

String languageToLoad = "en"; // your language 
Locale locale = new Locale(languageToLoad); 
Locale.setDefault(locale); 
Configuration config = new Configuration(); 
config.locale = locale; 
getBaseContext().getResources().updateConfiguration(config, 
getBaseContext().getResources().getDisplayMetrics()); 
+0

Mã của bạn có lỗi cú pháp trong dòng cuối cùng thứ hai. – Markus

2

Bạn có thể kiểm tra như thế này nếu bạn muốn kiểm tra xem có API thấp hơn 17

boolean isRightToLeft = TextUtilsCompat.getLayoutDirectionFromLocale(Locale 
       .getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL; 

HOẶC cho API 17 trở lên

boolean isRightToLeft = TextUtils.getLayoutDirectionFromLocale(Locale 
       .getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL;