source

앱 자체 내에서 로케일 변경

factcode 2023. 10. 21. 10:52
반응형

앱 자체 내에서 로케일 변경

내 사용자는 앱 내에서 로케일을 변경할 수 있습니다(전화 설정을 영어로 유지하되 프랑스어, 네덜란드어 또는 기타 언어로 내 앱의 내용을 읽을 수 있음).

1.5/1.6에서는 완벽하게 작동하지만 2.0에서는 더 이상 작동하지 않는 이유는 무엇입니까?

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch(item.getItemId()) {
    case 201:
        Locale locale2 = new Locale("fr"); 
        Locale.setDefault(locale2);
        Configuration config2 = new Configuration();
        config2.locale = locale2;
        getBaseContext().getResources().updateConfiguration(
            config2, getBaseContext().getResources().getDisplayMetrics());
        // loading data ...
        refresh();
        // refresh the tabs and their content
        refresh_Tab ();   
     break;
     case 201: etc...

문제는 사용자가 위의 코드 행을 통과할 때마다 메뉴가 점점 더 "축소"된다는 것입니다.

축소되는 메뉴입니다.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    menu.add(0, 100, 1, "REFRESH").setIcon(android.R.drawable.ic_menu_compass);
    SubMenu langMenu = menu.addSubMenu(0, 200, 2, "NL-FR").setIcon(android.R.drawable.ic_menu_rotate);
        langMenu.add(1, 201, 0, "Nederlands");
        langMenu.add(1, 202, 0, "Français");
    menu.add(0, 250, 4, R.string.OptionMenu2).setIcon(android.R.drawable.ic_menu_send);
    menu.add(0, 300, 5, R.string.OptionMenu3).setIcon(android.R.drawable.ic_menu_preferences);
    menu.add(0, 350, 3, R.string.OptionMenu4).setIcon(android.R.drawable.ic_menu_more);
    menu.add(0, 400, 6, "Exit").setIcon(android.R.drawable.ic_menu_delete);

    return super.onCreateOptionsMenu(menu);
}

이것을 다시 작동시키려면 API 레벨 5에서 무엇을 해야 합니까?

테스트를 원하는 경우 전체 코드는 다음과 같습니다.

import java.util.Locale;

import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.widget.Toast;

public class Main extends Activity {
    /** Called when the activity is first created. */


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

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        SubMenu langMenu = menu.addSubMenu(0, 200, 2, "NL-FR").setIcon(android.R.drawable.ic_menu_rotate);
            langMenu.add(1, 201, 0, "Nederlands");
            langMenu.add(1, 202, 0, "Français");

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()){

        case 201:

            Locale locale = new Locale("nl"); 
            Locale.setDefault(locale);
            Configuration config = new Configuration();
            config.locale = locale;
            getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
            Toast.makeText(this, "Locale in Nederlands !", Toast.LENGTH_LONG).show();
            break;

        case 202:

            Locale locale2 = new Locale("fr"); 
            Locale.setDefault(locale2);
            Configuration config2 = new Configuration();
            config2.locale = locale2;
            getBaseContext().getResources().updateConfiguration(config2, getBaseContext().getResources().getDisplayMetrics());

            Toast.makeText(this, "Locale en Français !", Toast.LENGTH_LONG).show();
            break;  

        }
        return super.onOptionsItemSelected(item);
    }
}

그리고 여기 그 선언문이 있습니다.

<?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.cousinHub.ChangeLocale"
          android:versionCode="1"
          android:versionName="1.0">
        <application android:icon="@drawable/icon" android:label="@string/app_name">
            <activity android:name=".Main"
                      android:label="@string/app_name">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
        <uses-sdk android:minSdkVersion="3" /> 
    </manifest>

이것이 제가 찾은 것입니다.

<uses-sdk android:minSdkVersion="5" />

=> 잘 작동합니다...

<uses-sdk android:minSdkVersion="3" />

=> 로케일 변경시마다 메뉴 축소!!!

1.5에서 사용자가 애플리케이션에 액세스할 수 있도록 유지하고 싶은데 어떻게 해야 합니까?

원래 질문은 로케일 자체에 관한 것이 아니라 다른 로케일 관련 질문은 모두 이 질문과 관련된 것입니다.그래서 여기서 그 문제를 분명히 하고 싶었습니다.저는 이 질문을 저만의 로케일 스위칭 코드의 시작점으로 삼았는데 방법이 정확하지 않다는 것을 알게 되었습니다.구성이 변경될 때(예: 화면 회전)에만 작동하고 해당 특정 활동에서만 작동합니다.한동안 코드를 가지고 놀다가 다음과 같은 접근법을 얻었습니다.

저는 안드로이드.앱을 확장하였습니다.응용프로그램에 다음 코드를 추가했습니다.

public class MyApplication extends Application
{
    private Locale locale = null;

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

    @Override
    public void onCreate()
    {
        super.onCreate();

        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);

        Configuration config = getBaseContext().getResources().getConfiguration();

        String lang = settings.getString(getString(R.string.pref_locale), "");
        if (! "".equals(lang) && ! config.locale.getLanguage().equals(lang))
        {
            locale = new Locale(lang);
            Locale.setDefault(locale);
            config.locale = locale;
            getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
        }
    }
}

이 코드를 사용하면 모든 활동에 사용자 지정 로케일이 설정되며 회전 및 기타 이벤트가 재설정되지 않습니다.

또한 많은 시간을 들여 환경설정 변경을 바로 적용하려고 했지만 성공하지 못했습니다. Activity 재시작 시 언어가 올바르게 변경되었지만 전체 응용프로그램을 재시작할 때까지 번호 형식 및 기타 로케일 속성이 적용되지 않았습니다.

변경사항AndroidManifest.xml

추가하는 것을 잊지 마세요.android:configChanges="layoutDirection|locale"Android 및 Android Manifest의 Android Manifest의 활동에 할 수 .android:name=".MyApplication"<application>요소.

숙면을 취한 후 웹에서 답을 찾았습니다(다음 줄에서 간단한 구글 검색"getBaseContext().getResources().updateConfiguration(mConfig, getBaseContext().getResources().getDisplayMetrics());"), 여기 있습니다:

link text => 이 링크도 표시됩니다.screenshots무슨 일이 일어나고 있는지를!

밀도가 여기서 문제였습니다. Android Manifest.xml에 이것이 있어야 했습니다.

<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true"
/>

가장 중요한 것은 안드로이드입니다: anyDensity = "true."

에 다음 사항을 추가하는 것을 잊지 마십시오.AndroidManifest.xml모든 활동(Android 4.1 이하의 경우):

android:configChanges="locale"

이 버전은 Android 4.2(API 레벨 17) 설명을 작성할 때 필요합니다.

android:configChanges="locale|layoutDirection"

안드로이드 M에서는 최고의 솔루션이 작동하지 않습니다.응용 프로그램 클래스와 모든 활동에서 호출해야 하는 내용을 수정하기 위해 도우미 클래스를 작성했습니다(기본 활동을 작성한 후 모든 활동을 상속하도록 하는 것이 좋습니다).

참고: 이는 RTL 레이아웃 방향도 올바르게 지원합니다.

도우미 클래스:

public class LocaleUtils {

    private static Locale sLocale;

    public static void setLocale(Locale locale) {
        sLocale = locale;
        if(sLocale != null) {
            Locale.setDefault(sLocale);
        }
    }

    public static void updateConfig(ContextThemeWrapper wrapper) {
        if(sLocale != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Configuration configuration = new Configuration();
            configuration.setLocale(sLocale);
            wrapper.applyOverrideConfiguration(configuration);
        }
    }

    public static void updateConfig(Application app, Configuration configuration) {
        if (sLocale != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
            //Wrapping the configuration to avoid Activity endless loop
            Configuration config = new Configuration(configuration);
            // We must use the now-deprecated config.locale and res.updateConfiguration here,
            // because the replacements aren't available till API level 24 and 17 respectively.
            config.locale = sLocale;
            Resources res = app.getBaseContext().getResources();
            res.updateConfiguration(config, res.getDisplayMetrics());
        }
    }
}

응용프로그램:

public class App extends Application {
    public void onCreate(){
        super.onCreate();

        LocaleUtils.setLocale(new Locale("iw"));
        LocaleUtils.updateConfig(this, getBaseContext().getResources().getConfiguration());
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        LocaleUtils.updateConfig(this, newConfig);
    }
}

기본 활동:

public class BaseActivity extends Activity {
    public BaseActivity() {
        LocaleUtils.updateConfig(this);
    }
}

Andrey의 답변에 대한 제 의견인데 댓글에 코드를 넣을 수가 없습니다.

선호하는 활동이 주 활동에서 호출되는 것입니까?이력서에 이것을 넣을 수첩에 넣어주시면...

@Override
protected void onResume() {
    if (!(PreferenceManager.getDefaultSharedPreferences(
            getApplicationContext()).getString("listLanguage", "en")
            .equals(langPreference))) {
        refresh();
    }
    super.onResume();
}

private void refresh() {
    finish();
    Intent myIntent = new Intent(Main.this, Main.class);
    startActivity(myIntent);
}

Android: anyDensity="true"를 사용할 수 없었습니다. 왜냐하면 게임의 오브젝트는 완전히 다른 위치에 있기 때문입니다.이것 또한 효과가 있는 것 같습니다.

// 로케일 생성로케일2 = 새 로케일(loc);로캘.setDefault(locale2);
Configuration2 = new Configuration();config2. locale = local2;
// 로케일 업데이트mContext.getResources().updateConfiguration(config2, null);

로케일을 즉시 변경할 수 있는 메뉴 옵션을 적용하려면 다음과 같이 하십시오.이렇게 해야 돼요.

//onCreate method calls only once when menu is called first time.
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    //1.Here you can add your  locale settings . 
    //2.Your menu declaration.
}
//This method is called when your menu is opend to again....
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
    menu.clear();
    onCreateOptionsMenu(menu);
    return super.onMenuOpened(featureId, menu);
}

언급URL : https://stackoverflow.com/questions/2264874/changing-locale-within-the-app-itself

반응형