web-dev-qa-db-fra.com

Forcer la direction de la mise en page RTL ne fonctionne pas pour l'application

J'essaie d'ajouter le support de la langue RTL dans mon application (en particulier l'arabe en ce moment). Je soutiendrai également l'anglais. Ce que j'ai fait:

  • Définissez minSdkVersion sur 17
  • Ajoutée Android:supportsRtl="true" à ma balise d'application dans AndroidManifest.xml
  • Commuté mes attributs gauche/droite pour démarrer/terminer

Au début, j'ai apporté ces modifications manuellement, puis j'ai utilisé l'élément de menu Android Studio "Refactor -> Ajouter le support RTL si possible ...".

Lorsque je prévisualise mes fichiers de disposition, je peux voir que l'aperçu RTL reflète correctement l'interface utilisateur; cependant, même lorsque j'utilise la "Force RTL Layout Direction", mon application n'affiche pas la disposition RTL. L'interface utilisateur du système est inversée, de sorte que cette option fonctionne en général.

Dois-je faire autre chose pour afficher la disposition RTL? J'espère avoir raté quelque chose d'évident. Je teste cela sur un émulateur API 21.

Mise à jour

J'ai hérité d'une partie de ce code. Quelque chose pourrait remplacer un paramètre et le forcer en mode LTR. J'ai fait une application de test pour tester le mode RTL et cela a bien fonctionné. Quel type de code peut entraîner le paramètre "Forcer la disposition RTL" à ignorer (ou à le remplacer)?

Mise à jour 2

J'ai vérifié que les paramètres régionaux sont définis correctement, et c'est le cas. J'ai également vérifié la configuration et ldrtl est défini. J'ai vérifié dans le fichier apk signé que Android:supportsRtl l'a fait et aucun des fichiers de mise en page n'avait Android:layoutDirection="ltr". J'ai même essayé de mettre manuellement Android:layoutDirection="rtl" pour essayer de forcer une mise en miroir, mais cela n'a pas fonctionné non plus. "

Mise à jour 3

J'ai ajouté une autre activité au projet, en ai fait l'activité de lancement et je me suis assuré qu'il n'était connecté à aucun code existant. C'est une sous-classe de Activity. Le problème existe toujours. Donc, théoriquement, c'est un problème de configuration. Comme je l'ai dit, j'ai vérifié le fichier AndroidManifest.xml et tous les fichiers de mise en page générés, ainsi que la prise en charge RTL et les modifications de mise en page.

27
Ben Kane

Bug le plus obscur jamais créé. Comme je l'ai mentionné dans la question, la plupart de ce code a été hérité. Cela a fini par être un problème d'opérateur au niveau du bit qui a vissé des drapeaux pour l'application. &= était utilisé au lieu de & pour vérifier si un indicateur a été défini.

Comme indiqué dans les commentaires, le code a été tiré d'un exemple dans un blog des développeurs Android , ce qui explique pourquoi tant d'autres ont rencontré ce même problème. J'ai déposé un rapport de bug et le blog a depuis été mis à jour en silence. Voici le code d'origine, que j'ai supprimé &= de. N'utilisez pas le code suivant tel quel. Vous devez changer &= à &:

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

Essaye ça...

  1. Créez une classe pour maintenir l'état global de l'application.

    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. Spécifiez la classe globale à votre balise AndroidManifest.xml, ce qui provoquera l'instanciation de cette classe avec vos paramètres régionaux enregistrés, lorsque le processus pour votre application/package sera créé. Comme, Android:name="com.your.package.YourGlobalClass" Android:supportsRtl="true"

  3. Créez les deux méthodes suivantes dans votre MainActivity.Java (où vous le souhaitez).

    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. Bon codage ...

2