解决方案之Android 国际化资源完美兼容6.0,7.0,8.0

在Android世界中,一般App应用的语言是根据Android系统显示的语言变化的,但是有时候有些应用需要单独设置App的显示语言。

Android 国际化实现

国际化一般最常用的是支持简体中文和美式英文。
思路:

  1. 切换Project视图
  2. 创建多个国家的资源文件夹
  3. 调用语言切换工具类(获取string.xml 通过Resource对象,然后更新)
  4. 在Application启动的时候加载修改语言方法
  5. 创建一个Activity基类,方便随时随地重启和替换掉所有界面的Context

1. 首先需要将项目切换到Project 视图(必要)

解决方案之Android 国际化资源完美兼容6.0,7.0,8.0_第1张图片

2. 建立资源文件夹(必要)

比如国际化需要支持简体中文和美式英语,需要这三个string.xml

  • values 默认的字符串资源文件,必须有
  • values-zh-rCN 简体中文字符串资源文件
  • values-en-rUS 美式英语字符串资源文件

解决方案之Android 国际化资源完美兼容6.0,7.0,8.0_第2张图片
格式规范: values-语言代码-r国家代码
例如:values-zh-rCN(中文)和values-en-rUS(英文)

这里可以考虑使用一些辅助工具:
国家_地区语言速查表

手动创建

  1. 选中res 文件夹右键,New ——> Android Resource Directory
  2. 选中Locale
    解决方案之Android 国际化资源完美兼容6.0,7.0,8.0_第3张图片
    3.选择要支持的资源文件夹

比如中文中国
解决方案之Android 国际化资源完美兼容6.0,7.0,8.0_第4张图片
选择英文美式
解决方案之Android 国际化资源完美兼容6.0,7.0,8.0_第5张图片

3. 中文和英文切换调用方法(必要)

MainActivity.java

  /**
     * App 语言切换成英文
     **/
    private void appLanguageSwitchToEnglish() {
        Locale locale=new Locale("en","US");
        //强制修改成英文
        LanguageUtil.changeAppLanguage(locale, true);
        //English 点击后按钮文字修改为简体中文
        loginPageSwitchLanguageButton.setText(getString(R.string.login_page_switch_language_Chinese_language));
        ToastTools.showLong(MyApplication.getContext(),"Current App Language Have Switch To English");
        //重启App
        restartApplication();
    }
    /**
     * App语言切换成中文
     */
    private void appLanguageSwitchToChinese() {
        Locale chineseLocale=new Locale("zh","CN");
        //强制切换成中文简体
        LanguageUtil.changeAppLanguage(chineseLocale, true);
        loginPageSwitchLanguageButton.setText(getString(R.string.login_page_switch_language_English_language));
        loginPageSwitchLanguageButton.invalidate();
        ToastTools.showLong(MyApplication.getContext(),"当前App语言已切换为简体中文");
        //重启应用
        restartApplication();
    }

4.语言切换工具类(必要)

LanguageUtil.java

public class LanguageUtil {

    public static Context appContext=MyApplication.getContext();

    /**
     * 更改应用语言
     * @param locale 语言地区
     * @param persistence 是否持久化
     */

    public static void changeAppLanguage(Locale locale, boolean persistence) {
        //获取应用程序的所有资源对象
        Resources resources = MyApplication.getContext().getResources();
        //获取屏幕参数
        DisplayMetrics metrics = resources.getDisplayMetrics();
        //获取设置对象
        Configuration configuration = resources.getConfiguration();
        //如果API < 17
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.locale = locale;
            appContext= MyApplication.getContext();
        } else //如果 17 < = API < 25 Android 7.7.1
            if(Build.VERSION.SDK_INT= 24
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            currentSystemLocale = Resources.getSystem().getConfiguration().getLocales().get(0);
        } else {
            currentSystemLocale = Resources.getSystem().getConfiguration().locale;
        }
        return currentSystemLocale;
    }
}

5. MyApplication中调用(必要)

MyApplication.java

public class MyApplication extends Application {

    /***
     * 系统上下文
     */
    private static Context context;
    @Override
    public void onCreate() {
        super.onCreate();
        context=getApplicationContext();
        Locale currentAppLocale=LanguageUtil.getAppLocale();
        LanguageUtil.changeAppLanguage(currentAppLocale,false);
    }

    public static Context getContext(){
        return context;
    }
}

6. BaseActivity替换所有的Context

SmartBaseActivity.java

public class SmartBaseActivity extends AppCompatActivity{
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    /***
     * 重启应用程序
     * */
    protected void restartApplication() {
        final Intent intent = MyApplication.getContext().getPackageManager().getLaunchIntentForPackage(getPackageName());
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);
    }

    @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(LanguageUtil.appContext);
    }
}

7. SharePreferencesTools 保存国际化状态(必要)

SharePreferencesTools.java

public class SharePreferencesTools {

    /**
     * 方法描述: SharePreferences 保存对象
     * 调用方法SharePreferencesSaveObject(Context context,String fileName,String key ,Object obj);
     * @param context  上下文对象
     * @param fileName SharePreference 文件名称
     * @param key Key
     * @param obj 要保存的对象
     * @return void
     * */
    /*******************SharePreferences 保存对象 *****************************/
    public static void saveObjectToSharePreferences(Context context, String fileName, String key, Object obj){
        try {
            // 保存对象
            SharedPreferences.Editor sharedata = context.getSharedPreferences(fileName,0).edit();
            //先将序列化结果写到byte缓存中,其实就分配一个内存空间
            ByteArrayOutputStream bos=new ByteArrayOutputStream();
            ObjectOutputStream os=new ObjectOutputStream(bos);
            //将对象序列化写入byte缓存
            os.writeObject(obj);
            //将序列化的数据转为16进制保存
            String bytesToHexString = bytesToHexString(bos.toByteArray());
            //保存该16进制数组
            sharedata.putString(key, bytesToHexString);
            sharedata.commit();
        } catch (IOException e) {
            e.printStackTrace();
            SmartLogUtils.debugInformation("保存Obj失败"+e.toString(),true);
        }
    }
    /**
     * desc:将数组转为16进制
     * @param bArray
     * @return String
     */
    private static String bytesToHexString(byte[] bArray) {
        if(bArray == null){
            return null;
        }
        if(bArray.length == 0){
            return "";
        }
        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        for (int i = 0; i < bArray.length; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2)
                sb.append(0);
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }
    /*******************SharePreferences 保存对象 *****************************/

    /**
     * 方法描述: 获取SharePreferences保存的Object对象
     * 调用方法     Object obj= readSharePreferencesObject(Context context,String fileName,String key );
     * @param context  上下文对象
     * @param filename 读取文件名
     * @param key
     * @return 异常返回null,成功返回该对象
     */
    /*******************读取 SharePreferences 保存对象 *****************************/
    public static Object readObjectFromSharePreferences(Context context,String fileName,String key ){
        try {
            SharedPreferences sharedata = context.getSharedPreferences(fileName, 0);
            if (sharedata.contains(key)) {
                String string = sharedata.getString(key,"");
                if(TextUtils.isEmpty(string)){
                    return null;
                }else{
                    //将16进制的数据转为数组,准备反序列化
                    byte[] stringToBytes = StringToBytes(string);
                    ByteArrayInputStream bis=new ByteArrayInputStream(stringToBytes);
                    ObjectInputStream is=new ObjectInputStream(bis);
                    //返回反序列化得到的对象
                    Object readObject = is.readObject();
                    return readObject;
                }
            }
        } catch (StreamCorruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //所有异常返回null
        return null;

    }
    /**
     * desc:将16进制的数据转为数组
     * @param  data
     * @return
     */
    private static byte[] StringToBytes(String data){
        String hexString=data.toUpperCase().trim();
        if (hexString.length()%2!=0) {
            return null;
        }
        byte[] retData=new byte[hexString.length()/2];
        for(int i=0;i= '0' && hex_char1 <='9')
                int_ch1 = (hex_char1-48)*16;   //// 0 的Ascll - 48
            else if(hex_char1 >= 'A' && hex_char1 <='F')
                int_ch1 = (hex_char1-55)*16; //// A 的Ascll - 65
            else
                return null;
            i++;
            char hex_char2 = hexString.charAt(i); ///两位16进制数中的第二位(低位)
            int int_ch2;
            if(hex_char2 >= '0' && hex_char2 <='9')
                int_ch2 = (hex_char2-48); //// 0 的Ascll - 48
            else if(hex_char2 >= 'A' && hex_char2 <='F')
                int_ch2 = hex_char2-55; //// A 的Ascll - 65
            else
                return null;
            int_ch = int_ch1+int_ch2;
            retData[i/2]=(byte) int_ch;//将转化后的数放入Byte里
        }
        return retData;
    }
    /*******************读取 SharePreferences 保存对象 *****************************/
}

8. 吐司工具类 (非必须)

/**
 * Toast 弹出信息工具类,简化代码编写
 * @author fairy
 * */
public class SmartToastUtils{
    public static void showLong(String info) {
        Toast.makeText(MyApplication.getContext(),info, Toast.LENGTH_LONG).show();
    }
    public static void showShort(String info) {
        Toast.makeText(MyApplication.getContext(),info,Toast.LENGTH_SHORT).show();
    }
}

9. 日志工具类(非必要)

public class SmartLogUtils {

    /***
     * 封装日志打印方法
     * @param  message 打印的消息
     * @param  showMessage 是否显示打印的消息
     * **/
    public static void debugInformation(String message,Boolean showMessage){
        if(showMessage){
            int max_str_length = 2001 - DebugConstant.DEBUG_TAG.length();
            //大于4000时
            while (message.length() > max_str_length) {
                Log.e(DebugConstant.DEBUG_TAG, message.substring(0, max_str_length));
                message = message.substring(max_str_length);
            }
            //剩余部分
            Log.e(DebugConstant.DEBUG_TAG,message);
        }
    }

    private final static String DEBUG_TAG="xingyun";
    /***
     * 封装日志打印方法
     * @param  message 打印的消息
     * @param  showMessage 是否显示打印的消息
     * **/
    public static void showInfo(String message,Boolean showMessage){
        if(showMessage){
            int max_str_length = 2001 - DEBUG_TAG.length();
            //大于4000时
            while (message.length() > max_str_length) {
                Log.i(DEBUG_TAG, message.substring(0, max_str_length));
                message = message.substring(max_str_length);
            }
            //剩余部分
            Log.i(DEBUG_TAG,message);
        }
    }

    /***
     * 封装日志打印方法
     * @param  message 打印的消息
     * @param  showMessage 是否显示打印的消息
     * **/
    public static void showDebug(String message,Boolean showMessage){
        if(showMessage){
            int max_str_length = 2001 - DEBUG_TAG.length();
            //大于4000时
            while (message.length() > max_str_length) {
                Log.d(DEBUG_TAG, message.substring(0, max_str_length));
                message = message.substring(max_str_length);
            }
            //剩余部分
            Log.d(DEBUG_TAG,message);
        }
    }

    public static void showError(String message,Boolean showMessage){
        if(showMessage){
            int max_str_length = 2001 - DEBUG_TAG.length();
            //大于4000时
            while (message.length() > max_str_length) {
                Log.e(DEBUG_TAG, message.substring(0, max_str_length));
                message = message.substring(max_str_length);
            }
            //剩余部分
            Log.e(DEBUG_TAG,message);
        }
    }
}

本篇完~
如有疑问欢迎留言~

你可能感兴趣的:(#,Android)