通俗易懂地讲解Android app国际化实现方式,开发需要注意的地方

来源:互联网 发布:java 广告位管理系统 编辑:程序博客网 时间:2024/06/05 03:56

   国际化的实现只需要将res目录下的资源按照对应的规则命名即可,比如:

这里写图片描述

图片资源(不一定是mipmap,也可以是drawable)只需要命名相同,字符资源id相同。
zh-rCN表示中国,zh-rTW表示台湾,更多国家的名称缩写可以参考 http://www.cnblogs.com/linlf03/p/3680454.html

布局文件:

<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:gravity="center">    <ImageView        android:id="@+id/iv_main_img"        android:layout_width="32dp"        android:layout_height="32dp"        android:scaleType="centerCrop"/>    <TextView        android:id="@+id/tv_main_str"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="10dp"        android:textSize="18sp"        android:maxLines="1"/></LinearLayout>

MainActivity:

public class MainActivity extends Activity {    private ImageView mImg;    private TextView mStr;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Log.d("mydebug---", "onCreate : "+this.toString());        mImg = findViewById(R.id.iv_main_img);        mStr = findViewById(R.id.tv_main_str);        setInfo();    }    private void setInfo(){        mImg.setImageResource(R.mipmap.online);        mStr.setText(getString(R.string.app_name));    }}

运行截图(系统语言为台湾繁体):

这里写图片描述

   资源配置完成,接下来看系统语言发生改变时,程序如何接收。先在清单文件给MainActivity配置:

android:configChanges="locale"

在MainActivity里添加:

    @Override    public void onConfigurationChanged(Configuration newConfig) {        super.onConfigurationChanged(newConfig);        Log.d("mydebug---", "MainActivity onConfigurationChanged");        setInfo();    }

同时创建一个Application类,并在清单文件的application标签配置此类:

public class App extends Application {    @Override    public void onConfigurationChanged(Configuration newConfig) {        super.onConfigurationChanged(newConfig);        Log.d("mydebug---", "App onConfigurationChanged");    }}

从名字就可以看出这两个onConfigurationChanged函数都是系统配置发生变动时的回调函数。
再次运行,如下操作:
这里写图片描述

输出日志:

10-16 21:42:28.310 15381-15381/hankin.international D/mydebug---: onCreate : hankin.international.MainActivity@d68835f10-16 21:42:35.230 15381-15381/hankin.international D/mydebug---: App onConfigurationChanged10-16 21:42:35.862 15381-15381/hankin.international D/mydebug---: onCreate : hankin.international.MainActivity@b236bc2

从日志可以看出在切换系统语言时,系统回调了application的onConfigurationChanged函数,但是MainActivity却重新创建了,这样会使程序逻辑非常不可控,我们需要的是MainActivity不重建,只回调onConfigurationChanged函数。接下来修改清单文件中MainActivity的配置为:

android:configChanges="locale|layoutDirection"

再次运行,重复上面的修改系统语言操作:
这里写图片描述

日志:

10-16 21:56:12.459 26881-26881/hankin.international D/mydebug---: onCreate : hankin.international.MainActivity@8e400d10-16 21:56:25.560 26881-26881/hankin.international D/mydebug---: App onConfigurationChanged10-16 21:56:27.051 26881-26881/hankin.international D/mydebug---: MainActivity onConfigurationChanged

   可以看到MainActivity并没有重新创建了。这里需要注意的是MainActivity onConfigurationChanged是在回到应用程序的时候才会调用,且在onRestart之前调用。
   应用随系统语言切换而改变写好后,可能还会碰到另一种需求:那就是在不管系统语言是什么,在应用内都显示成某种语言。
   为了模拟这种需求我们在布局文件添加两个按钮:

    <Button        android:id="@+id/btn_main_en"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="10dp"        android:onClick="click"        android:text="设置为英文"/>    <Button        android:id="@+id/btn_main_zh"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="10dp"        android:onClick="click"        android:text="設置為繁體字"/>

在MainActivity中添加:

    private void changeLanguage(String language) {        //设置应用语言类型        Resources resources = getResources();        Configuration config = resources.getConfiguration();        DisplayMetrics dm = resources.getDisplayMetrics();        if (language.equals("en")) {            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {                config.setLocale(Locale.ENGLISH);            } else {                config.locale = Locale.ENGLISH;            }        } else if(language.equals("zh")) {            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {                config.setLocale(Locale.TAIWAN);            } else {                config.locale = Locale.TAIWAN;            }        }        //只会改变此应用的Configuration,对于系统的getApplicationContext().getResources().getConfiguration().locale不变        //在应用被强制停止前,应用的Configuration都是更改后的Configuration        resources.updateConfiguration(config, dm);//api25后推荐使用contenxt.createConfigurationContext(config);        //更改了应用的Configuration后,不会回调其他函数,需要手动更新UI        Intent intent = new Intent(this, MainActivity.class);        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);        startActivity(intent);    }    @Override    protected void onNewIntent(Intent intent) {        super.onNewIntent(intent);        Log.d("mydebug---", "MainActivity onNewIntent");        setInfo();    }    public void click(View view){        switch (view.getId()){            case R.id.btn_main_en:                changeLanguage("en");                break;            case R.id.btn_main_zh:                changeLanguage("zh");                break;        }    }

需要注意的是调用

resources.updateConfiguration(config, dm);

后,需要手动刷新一下页面,而且修改的Configuration会保存在当前进程,直到应用被杀死或接收到系统语言的改动。在实际开发中,这里可以做一个缓存,不管应用下次启动还是接受到系统语言的改动,都可以按用户设置的语言来显示app。

运行后,效果图:
这里写图片描述

项目源码

github下载

原创粉丝点击