android locale change in orientation change

2019-04-30 01:41发布

问题:

in my app i am having two activities one is rotatable to both sides and other is locked in landscape mode.

Following is my manifest file details where the activities been added

<activity
    android:name="com.hogaming.android.Activities.LoginActivity"
    android:configChanges="orientation|screenSize|keyboardHidden">
</activity>

<activity
    android:name="com.android.activities.MainActivity"
    android:configChanges="orientation|screenSize|keyboardHidden">
</activity>

in my login activity using a spinner i am changing the locale and updating entire edit texts and buttons text. In a button click action i am updating the UI views and that time when i rotate the device, the English locale is set on views which are updated Here is my entire code

public class LoginActivity extends Activity 
{
    Locale locale = null;
    Spinner langSpinner;
    private SharedPreferences langPrefs;
    String langSelected = "";
    int langPosition = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.loginscreen);

        langPrefs = PreferenceManager.getDefaultSharedPreferences(this);
        langSelected = langPrefs.getString(langPrefKey, "");
        langPosition = langPrefs.getInt(langPosKey, 0);

        langSpinner = (Spinner)this.findViewById(R.id.lanuage_spinner1);
        langSpinner.setSelection(langPosition);
        langSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() 
        {
            @Override
            public void onItemSelected(AdapterView<?> arg0, View arg1, int pos, long arg3) 
            {   
                if (pos == 0) 
                {
                    langSelected ="en";
                    locale = Locale.ENGLISH;
                }
                else if (pos == 1) 
                {
                    langSelected ="it";
                    locale = Locale.ITALIAN;
                } 
                else if (pos == 2) 
                {
                    langSelected ="zh";
                    locale = Locale.SIMPLIFIED_CHINESE;
                }               
                else if (pos == 3)
                {
                    langSelected ="zh-rTW";
                    locale = Locale.TRADITIONAL_CHINESE;
                }
                changeLang(langSelected, pos);
            }
            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
                // TODO Auto-generated method stub

            }   
        });

        btnLogin = (Button) this.findViewById(R.id.LoginButton);
        btnLogin.setOnClickListener(new ButtonClickListener());
    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    @Override
    protected void onStop() {
        super.onStop();
        this.finish();
    }

    @Override
    protected void onDestroy() 
    {
        super.onDestroy();
        this.finish();
    }

    public class ButtonClickListener implements OnClickListener {
        public void onClick(View v) {
                    final LoginTask validateTask = new LoginTask(context, usernameField.getText().toString(), passwordField.getText().toString());
                    validateTask.execute();
                }

                // Hide the keyboard
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(passwordField.getWindowToken(), 0);
    }

    public class LoginTask extends AsyncTask<Void, Void, String> 
    {
        protected LoginActivity context;
        protected Exception exception;
        private String username;
        private String password;

        public LoginTask(LoginActivity context, String uname, String pwd) {
            this.context = context;
            this.username = uname;
            this.password = pwd;
        }

        @Override
        protected String doInBackground(Void... params) {
            try 
            {
                return HTTPHelper.LoginTaskData(this.context, username, password);
            }
            catch (Exception e) 
            {
                exception = e;
                Log.e(TAG, "Login Task Error", e);
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) 
        {
            super.onPostExecute(result);
            Log.e(TAG, "LoginTask: " + result);
            if (result.equals("true")) 
            {
                // moves to next activity
            }
            else if (result.equals("false"))
            {
                //showing an alert textview with selected language text
            }
        }
    }

    public void changeLang(String lang, int pos)
    {
        if (lang.length() != 0)
        {       
            saveLocale(lang, pos, locale);
            android.content.res.Configuration config = new android.content.res.Configuration();
            config.locale = locale;
            Locale.setDefault(locale);
            getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
            updateTexts();
        }
    }

    public void saveLocale(String lang, int pos, Locale locale)
    {
        SharedPreferences.Editor editor1 = langPrefs.edit();
        editor1.remove(langPrefKey);
        editor1.remove(langPosKey);
        editor1.commit();

        SharedPreferences.Editor editor = langPrefs.edit();
        editor.putString(langPrefKey, lang);
        editor.putInt(langPosKey, pos);
        editor.commit();

        langSelected = langPrefs.getString(langPrefKey, "");
        langPosition = langPrefs.getInt(langPosKey, 0);
    }

    private void updateTexts()
    {
        // here i will once again set all textview String values, it changes to the selected language
    }

    @Override
    public void onConfigurationChanged(android.content.res.Configuration newConfig) 
    {
        super.onConfigurationChanged(newConfig);
        if (locale != null){
            newConfig.locale = locale;
            Locale.setDefault(locale);
            getBaseContext().getResources().updateConfiguration(newConfig, getBaseContext().getResources().getDisplayMetrics());
        }
    }
}

回答1:

If I understood you correctly, the issue is that the phone's locale is restored when you switch the screen orientation, despite you have android:configChanges="orientation|screenSize|keyboardHidden", in your AndroidManifest.xml. If I were in you I would approach the issue from a different perspective. I would get rid of the android:configChanges, letting android do its job restarting the Activity, when the orientation changes. I would then use the pair onSaveInstanceState, to save and the Locale the user selected in the Spinner. When onCreate is called again, and you know is called due to the orientation change because the bundle is not null, read the Locale stored and restart, and update the configuration again. E.g.

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    savedInstanceState.putSerializable("LOCALE", locale);
    super.onSaveInstanceState(savedInstanceState);
}

@Override
public void onCreate(Bundle savedInstanceState)  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.loginscreen);
    if (savedInstanceState != null) {
        locale = (Locale) savedInstanceState.getSerializable("LOCALE");
        if (locale != null) {
           // update the configuration 
        }
    }


回答2:

You still have the solution. just set the saved locale. in the onCreate:

    ...
    langPrefs = PreferenceManager.getDefaultSharedPreferences(this);
    langSelected = langPrefs.getString(langPrefKey, "");
    langPosition = langPrefs.getInt(langPosKey, 0);

    // JUST ADD THIS LINE HERE
    changeLang(langSelected, langPosition);  
    // no need to check empty langSelected, it handled inside of changeLang as you write.

    langSpinner = (Spinner)this.findViewById(R.id.lanuage_spinner1);
    ....

maybe you need to remove android:configChanges and its corresponding method.



回答3:

I think you should put following code when fixed orientation of particular activity in manifest file:

<activity
     android:name="Your_Activity"
     android:configChanges="orientation"
     android:screenOrientation="landscape" />


回答4:

Just add this to your activity

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    setlocal();// the code for setting your local
}