web-dev-qa-db-ja.com

アプリでRTLレイアウトの方向が強制的に機能しない

RTL言語のサポートをアプリに追加しようとしています(特にアラビア語)。英語もサポートします。私がやったこと:

  • MinSdkVersionを17に設定します
  • Android:supportsRtl="true"のアプリケーションタグにAndroidManifest.xmlを追加しました
  • 左/右の属性を開始/終了に切り替えました

最初にこれらの変更を手動で行った後、Android Studioの[リファクタリング->可能な場合はRTLサポートを追加...]メニュー項目を使用しました。

レイアウトファイルをプレビューすると、RTLプレビューがUIを適切にミラーリングしていることがわかります。ただし、「Force RTL Layout Direction」を使用しても、アプリにはRTLレイアウトが表示されません。システムUIは反転されているため、このオプションは一般的に機能します。

RTLレイアウトを表示するために必要なことは他にありますか?明らかな何かを見逃したことを望んでいます。これをAPI 21エミュレーターでテストしています。

更新

このコードの一部を継承しました。何かが設定を上書きし、これを強制的にLTRモードにする可能性があります。 RTLモードをテストするためのテストアプリケーションを作成し、正常に機能しました。どのようなコードにより、「RTLレイアウトの方向を強制する」設定が無視される(または上書きされる)可能性がありますか?

更新2

ロケールが適切に設定されていることを確認しました。構成も確認し、ldrtlが設定されています。署名済みのapkファイルでAndroid:supportsRtlが作成され、レイアウトファイルにAndroid:layoutDirection="ltr"がないことを確認しました。私は手動でAndroid:layoutDirection="rtl"を入れてレイアウトを強制的にミラー化しようとしましたが、それも機能しませんでした。

アップデート3

別のアクティビティをプロジェクトに追加し、ランチャーアクティビティにし、既存のコードに接続されていないことを確認しました。 Activityのサブクラスです。問題はまだ存在します。理論的には、これは構成の問題です。私が言ったように、AndroidManifest.xmlファイルと生成されたすべてのレイアウトファイルをチェックし、RTLサポートとレイアウトの変更がすべて行われました。構成で何が問題になる可能性がありますか?

27
Ben Kane

これまでで最も不明瞭なバグ。質問で述べたように、このコードのほとんどは継承されました。それは、アプリケーションのフラグを台無しにしていたビット単位の演算子の問題になってしまいました。 &=の代わりに&を使用して、フラグが設定されているかどうかを確認していました。

コメントに記載されているように、コードは Android Developersブログ投稿 の例から引用されています。私はバグレポートを提出し、ブログ投稿はその後静かに更新されました。元のコードは次のとおりです。&=を削除しました。 次のコードをそのまま使用しないでください。 &=&に変更する必要があります

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

これを試して...

  1. グローバルアプリケーションの状態を維持するクラスを作成します。

    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. AndroidManifest.xmlのタグにグローバルクラスを指定します。これにより、アプリケーション/パッケージのプロセスが作成されたときに、保存されたロケールでそのクラスがインスタンス化されます。お気に入り、 Android:name="com.your.package.YourGlobalClass" Android:supportsRtl="true"

  3. MainActivity.Javaで次の2つのメソッドを作成します(必要な場合)。

    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
    }
    
  4. ハッピーコーディング...