强制 RTL 布局方向不适用于应用程序

Force RTL layout direction not working for app

我正在尝试在我的应用程序中添加 RTL 语言支持(现在特别是阿拉伯语)。我也会支持英语。我做了什么:

起初我手动进行了这些更改,然后我使用了 Android Studio 的 "Refactor -> Add RTL Support Where Possible..." 菜单项。

当我预览我的布局文件时,我可以看到 RTL 预览正确地反映了 UI;然而,即使我使用 "Force RTL Layout Direction",我的应用程序也不显示 RTL 布局。系统 UI 已翻转,因此该选项通常有效。

我还需要做些什么来显示 RTL 布局吗?我希望我错过了一些明显的东西。我正在 API 21 模拟器上对此进行测试。

更新

我继承了部分代码。某些东西可能会覆盖设置并强制其进入 LTR 模式。我做了一个测试应用程序来测试 RTL 模式,它运行良好。什么样的代码会导致 "Force RTL Layout Direction" 设置被忽略(或被覆盖)?

更新 2

我检查过区域设置是否设置正确,确实如此。我还检查了配置,设置了ldrtl。我在已签名的 apk 文件中验证了 android:supportsRtl 的内容,并且 none 的布局文件具有 android:layoutDirection="ltr"。我什至尝试手动放置 android:layoutDirection="rtl" 以尝试强制布局镜像,但这也没有用。`

更新 3

我向项目添加了另一个 activity,将其设为启动器 activity,并确保它未连接到任何现有代码。它是 Activity 的子类。问题仍然存在。所以理论上这是一个配置问题。就像我说的,我检查了 AndroidManifest.xml 文件和所有生成的布局文件,RTL 支持和布局更改都包含在内。配置可能出了什么问题?

试试这个...

  1. 创建一个class来维护全局应用程序状态。

     public class YourGlobalClass extends Application {
    
       @Override
       public void onCreate() {
       updateLanguage(this, null);
       super.onCreate();
       }
    
     public static void updateLanguage(Context ctx, String lang) {
    
      Configuration cfg = new Configuration();
      LocalSharedManager manager = new LocalSharedManager(ctx);
      String language = manager.GetValueFromSharedPrefs("force_locale");
    
         if (TextUtils.isEmpty(language) && lang == null) {
            cfg.locale = Locale.getDefault();
            String tmp_locale = "";
            tmp_locale = Locale.getDefault().toString().substring(0, 2);
            manager.SaveValueToSharedPrefs("force_locale", tmp_locale);
    
        } else if (lang != null) {
            cfg.locale = new Locale(lang);
            manager.SaveValueToSharedPrefs("force_locale", lang);
    
        } else if (!TextUtils.isEmpty(language)) {
            cfg.locale = new Locale(language);
        }
        ctx.getResources().updateConfiguration(cfg, null);
       }
    
     }
    
  2. 将全局 class 指定到您的 AndroidManifest.xml 的标签,这将导致 class 被实例化当您的 application/package 进程创建时,使用您保存的语言环境。比如,android:name="com.your.package.YourGlobalClass" android:supportsRtl="true"

  3. 在您的MainActivity.java(任何您想要的地方)中创建以下两个方法。

     public class MainActivity extends ActionBarActivity{
    
        .......
    
        // Implement OnclickListener for english_locale button
        findViewById(R.id.english_locale).setOnClickListener(new OnClickListener()
          {
    
             @Override
             public void onClick(View v)
             {
                 changeEnglish();
             }
          });
    
         // Implement OnclickListener for arabic_locale button
         findViewById(R.id.arabic_locale).setOnClickListener(new OnClickListener()
            {
    
               @Override
               public void onClick(View v)
                {
                   changeArabic();
                 }
            });
    
         /**
         * Method that Update UI for Arabic locale.
         */
         public void changeArabic() {
              new AsyncTask<Void, Void, Void>() {
    
              @Override
              protected Void doInBackground(Void... params) {
                   String app_locale = "ar";
                   Locale locale = new Locale(app_locale);
                   Locale.setDefault(locale);
    
                   //Configuration to query the current layout direction.
                   Configuration config = new Configuration();
                   config.locale = locale;
                   getResources().updateConfiguration(config,
                     getResources().getDisplayMetrics());
                   Bidi bidi = new Bidi(app_locale,
                     Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
                   bidi.isRightToLeft();
                   YourGlobalClass.updateLanguage(getActivity(), "ar");
    
                   //Refreshing current fragment
    
                   Intent i = getActivity().getIntent();
                   startActivity(i);
                   getActivity().finish();
                return null;
               }
    
            }.execute();
          }
    
             /**
             * Method that Update UI for Default(English) locale.
             */
           public void changeEnglish() {
    
               new AsyncTask<Void, Void, Void>() {
    
               @Override
               protected Void doInBackground(Void... params) {
                   String app_locale = "en";
                   Locale locale = new Locale(app_locale);
                   Locale.setDefault(locale);
    
                   //Configuration to query the current layout direction.
                   Configuration config = new Configuration();
                   config.locale = locale;
                   getResources().updateConfiguration(config,
                     getResources().getDisplayMetrics());
                   Bidi bidi = new Bidi(app_locale,
                     Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
                   bidi.isLeftToRight();
                   YourGlobalClass.updateLanguage(getActivity(), "en");
    
                   //Refreshing current fragment
                   Intent i = getActivity().getIntent();
                   startActivity(i);
                   getActivity().finish();
    
               return null;
               }
    
            }.execute();
          }
    
        ......
       //MainActivity end
     }
    

有史以来最晦涩的错误。正如我在问题中提到的,大部分代码都是继承而来的。它最终成为一个按位运算符问题,它搞砸了应用程序的标志。使用 &= 而不是 & 来检查是否设置了标志。

如评论中所述,代码取自 Android Developers blog post 中的示例,这解释了为什么有这么多其他人 运行 遇到了同样的问题。我提交了一个错误报告,博客 post 已经悄悄更新了。这是我从中删除 &= 的原始代码。 请勿按原样使用以下代码。您需要将 &= 更改为 &:

isDebuggable = (appContext.getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE) != 0;