Android支持国际化多语言那点事(支持8.0+)

起因

我们在开发app可能会拓展国外市场,那么对包含英语在内的其它语言支持就很有必要了。

效果

思路

一:添加相关资源文件,并引用。
二:设置configuration,configuration里面指定语言类型。
三:在需要时候更换configuration即可。

实现

在res的values文件夹下新建相关语言类型的资源文件

右键新建资源文件,选择Locale,点击 >> 按钮

选择Language,以及地区(any region)即可

最后 文件名字和其他语言文件名字一样,strings即可。

在MyApplication里面的onCreate和onConfigurationChanged方法里面添加语言相关处理(onConfigurationChanged是为了处理横竖屏切换问题),给应用上下文对象添加configuration,configuration里面指定了当前语言。

public class MyApplication extends Application {
@Override
public void onCreate() {
  super.onCreate();
  languageWork();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  languageWork();
}

private void languageWork() {
  //自己写的工具包(如下)
  Locale locale = LanguageUtil.getLocale(this);
  LanguageUtil.updateLocale(this, locale);
}
}

LanguageUtil如下(没整理过的小伙伴直接用即可),为了保证语言从A切换到B,在之后启动应用依旧使用B语言,我们需要将B语言存入本地。下次启动应用,设置即可。

public class LanguageUtil {
/**
 * 中文
 */
public static final Locale LOCALE_CHINESE = Locale.CHINESE;
/**
 * 英文
 */
public static final Locale LOCALE_ENGLISH = Locale.ENGLISH;
/**
 * 俄文
 */
public static final Locale LOCALE_RUSSIAN = new Locale("ru");

private static final String LOCALE_SP = "LOCALE_SP";
private static final String LOCALE_SP_KEY = "LOCALE_SP_KEY";

 public static Locale getLocale(Context context) {
  SharedPreferences spLocale = context.getSharedPreferences(LOCALE_SP, Context.MODE_PRIVATE);
  String localeJson = spLocale.getString(LOCALE_SP_KEY, "");
  Gson gson = new Gson();
  return gson.fromJson(localeJson, Locale.class);
}

pivate static void setLocale(Context pContext, Locale pUserLocale) {
  SharedPreferences spLocal = pContext.getSharedPreferences(LOCALE_SP, Context.MODE_PRIVATE);
  SharedPreferences.Editor edit = spLocal.edit();
  String json = new Gson().toJson(pUserLocale);
  edit.putString(LOCALE_SP_KEY, json);
  edit.apply();
}

public static boolean updateLocale(Context context, Locale locale) {
  if (needUpdateLocale(context, locale)) {
    Configuration configuration = context.getResources().getConfiguration();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
      configuration.setLocale(locale);
    } else {
      configuration.locale = locale;
    }
    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    context.getResources().updateConfiguration(configuration, displayMetrics);
    setLocale(context, locale);
    return true;
  }
  return false;
}

public static boolean needUpdateLocale(Context pContext, Locale newUserLocale) {
  return newUserLocale != null && !getCurrentLocale(pContext).equals(newUserLocale);
}
public static Locale getCurrentLocale(Context context) {
  Locale locale;
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //7.0有多语言设置获取顶部的语言
    locale = context.getResources().getConfiguration().getLocales().get(0);
  } else {
    locale = context.getResources().getConfiguration().locale;
  }
  return locale;
}
}

进行切换,主要触发动作是activity的recreate()(切换使用新的configuration)。所有的activity在activityManager里面进行管理。只需将其他(除了当前语言选择activity)的所有activity进行recreate(),即可。languageUtil同时进行了是否需要切换语言的判定。如果当前语言和要选择的一致,则无需再做处理)

 public void onClick(View view) {
  boolean need = false;
  switch (view.getId()) {
    case R.id.chinese:
      need = LanguageUtil.updateLocale(this, LanguageUtil.LOCALE_CHINESE);
      if (need) {
        //自己写的常用activity管理工具
        ActivityManager.getInstance().recreateAllOtherActivity(this);
        Toast.makeText(this, "change to chinese", Toast.LENGTH_SHORT).show();
      } else {
        Toast.makeText(this, "no need", Toast.LENGTH_SHORT).show();
      }
      break;
    case R.id.english:
      need = LanguageUtil.updateLocale(this, LanguageUtil.LOCALE_ENGLISH);
      if (need) {
        ActivityManager.getInstance().recreateAllOtherActivity(this);
        Toast.makeText(this, "change to english", Toast.LENGTH_SHORT).show();
      } else {
        Toast.makeText(this, "no need", Toast.LENGTH_SHORT).show();
      }
      break;
    case R.id.russian:
      need = LanguageUtil.updateLocale(this, LanguageUtil.LOCALE_RUSSIAN);
      if (need) {
        ActivityManager.getInstance().recreateAllOtherActivity(this);
        Toast.makeText(this, "change to russian", Toast.LENGTH_SHORT).show();
      } else {
        Toast.makeText(this, "no need", Toast.LENGTH_SHORT).show();
      }
      break;
  }
}

ActivityManager如下

 public class ActivityManager {
private static final Stack<Activity> sActivityStack = new Stack<>();
private static ActivityManager sActivityManager;

private ActivityManager() {
}

public Stack<Activity> getActivityStack() {
  return sActivityStack;
}

/**
 * 单一实例
 */
public static ActivityManager getInstance() {
  if (sActivityManager == null) {
    synchronized (ActivityManager.class) {
      sActivityManager = new ActivityManager();
    }
  }
  return sActivityManager;
}

/**
 * 添加Activity到堆栈
 */
public void addActivity(Activity activity) {
  sActivityStack.add(activity);
}

/**
 * 删除堆栈中的Activity
 */
public void removeActivity(Activity activity) {
  if (sActivityStack.isEmpty()) {
    return;
  }
  sActivityStack.remove(activity);
}

/**
 * 获取当前Activity(堆栈中最后一个压入的)
 */
public Activity currentActivity() {

  Activity activity = sActivityStack.lastElement();
  return activity;
}

/**
 * 结束当前Activity(堆栈中最后一个压入的)
 */
public void finishActivity() {
  Activity activity = sActivityStack.lastElement();
  finishActivity(activity);
}

/**
 * 结束指定的Activity
 */
public void finishActivity(Activity activity) {
  if (activity != null) {
    sActivityStack.remove(activity);
    activity.finish();
  }
}

/**
 * 结束指定类名的Activity
 */
public void finishActivity(Class<?> cls) {
  for (Activity activity : sActivityStack) {
    if (activity.getClass().equals(cls)) {
      finishActivity(activity);
      return;
    }
  }

}

//获取指定类名的Activity
public Activity getActivity(Class<?> cls) {
  for (Activity activity : sActivityStack) {
    if (activity.getClass().equals(cls)) {
      return activity;
    }
  }
  return null;
}

/**
 * 结束所有Activity
 */
public void finishAllActivity() {
  for (int i = 0, size = sActivityStack.size(); i < size; i++) {
    if (null != sActivityStack.get(i)) {
      sActivityStack.get(i).finish();
    }
  }
  sActivityStack.clear();
}

public void finishAllOtherActivity(Activity activity) {
  for (int i = 0, size = sActivityStack.size(); i < size; i++) {
    if (null != sActivityStack.get(i) && sActivityStack.get(i) != activity) {
      sActivityStack.get(i).finish();
    }
  }
  sActivityStack.clear();
}

public void recreateAllOtherActivity(Activity activity) {
  for (int i = 0, size = sActivityStack.size(); i < size; i++) {
    if (null != sActivityStack.get(i) && sActivityStack.get(i) != activity) {
      sActivityStack.get(i).recreate();
    }
  }
}

/**
 * 退出应用程序
 */
public void AppExit() {
  try {
    finishAllActivity();
    System.exit(0);
  } catch (Exception e) {
  }
  }
  }

将app的所有acitivity进行添加和移除,可以在BaseActivity里面进行。

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  ActivityManager.getInstance().addActivity(this);
}

@Override
protected void onDestroy() {
  super.onDestroy();
  ActivityManager.getInstance().removeActivity(this);
}

以上步骤,我们的语言切换算是完成了。但是,在API 26+以上版本,我们需要额外添加如下代码做兼容,没啥说的,SDK变动而已,跟着SDK走咯~(在activity或者BaseActivity添加)

 @Override
protected void attachBaseContext(Context newBase) {
  Context context = languageWork(newBase);
  super.attachBaseContext(context);

 }

private Context languageWork(Context context) {
  // 8.0及以上使用createConfigurationContext设置configuration
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    return updateResources(context);
  } else {
    return context;
  }
  }

@RequiresApi(api = Build.VERSION_CODES.O)
private Context updateResources(Context context) {
  Resources resources = context.getResources();
  Locale locale = LanguageUtil.getLocale(context);
  if (locale==null) {
    return context;
  }
  Configuration configuration = resources.getConfiguration();
  configuration.setLocale(locale);
  configuration.setLocales(new LocaleList(locale));
  return context.createConfigurationContext(configuration);
  }

完工~

地址:https://github.com/HoldMyOwn/MultiLanguage

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android自定义控件实现颜色选择器

    ColorPickerView 是之前一个智能家居项目实战中所写的自定义控件,主要用于取得RGB 0~255范围的值,然后转换成十六进制0~FF的值,发送给网关控制RGB彩灯.参考的是网上一个朋友的源码写的,多的不说了,先看效果图 activity_mian.xml文件: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas

  • Android自定义View实现颜色选取器

    Android 自定义View 颜色选取器,可以实现水平.竖直选择颜色类似 SeekBar 的方式通过滑动选择颜色. 效果图 xml 属性 1.indicatorColor 指示点颜色 2.indicatorEnable 是否使用指示点 3.orientation 方向 horizontal 水平 vertical 竖直 使用 复制 \library\src-\ColorPickerView.java 和 \library\src\main\res\values\attrs.xml 文件到你的项

  • Android实现颜色选取圆盘

    本文实例为大家分享了Android实现颜色选取圆盘的具体代码,供大家参考,具体内容如下 先看效果图 xml布局 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android

  • Android自定义view实现图片选色器

    简介 本文介绍该自定义view的使用及实现的方法,主要实现以下几个功能: - 选取圆盘选色图片上的颜色,实时监听 - 可设置选色指示图片,跟随触摸位置.指示所选颜色,示例中为白色圆环 - 可自己设置选色图片(目前只支持圆形图片) github链接 使用效果 首先看下使用效果: 使用示例 在项目中导入该库 在工程的 build.gradle中加入: allprojects { repositories { ... maven { url "https://jitpack.io" } }

  • android自定义View实现圆环颜色选择器

    最近工作需要,自定了一个颜色选择器,效果图如下: 颜色种类是固定的,圆环上有个指示器,指示选中的颜色,这个定义起来应该是很简单了,直接上代码. public class MyColorPicker extends View { private int mThumbHeight; private int mThumbWidth; private String[] colors ; private int sections; //每个小块的度数 private int sectionAngle; p

  • Android支持国际化多语言那点事(支持8.0+)

    起因 我们在开发app可能会拓展国外市场,那么对包含英语在内的其它语言支持就很有必要了. 效果 思路 一:添加相关资源文件,并引用. 二:设置configuration,configuration里面指定语言类型. 三:在需要时候更换configuration即可. 实现 在res的values文件夹下新建相关语言类型的资源文件 右键新建资源文件,选择Locale,点击 >> 按钮 选择Language,以及地区(any region)即可 最后 文件名字和其他语言文件名字一样,strings

  • 为Android添加一门新语言的解决办法

    虽然Android从2.3开始已经支持50种以上的语言,但是不是每种语言都有字体可以显示.遇到一个新需求,有客户要求对hindi语言的支持.于是上网找了一些资料,发现网上介绍的大部分是如何替换默认字体,就是替换./frameworks/base/data/fonts/DroidSansFallback.ttf,但是替换完之后,中文就无法正常显示.其实只要有下面几个步骤,就可以实现新曾加一种语言的显示支持:1. 需要有可以显示hindi语言的字体,我在网上下载了一个:DroidHindi.ttf2

  • Android轻松实现多语言的方法示例

    本文介绍了Android轻松实现多语言的方法示例,分享给大家,具体如下: 1.创建多语言包 2.首先在onCreate方法中调用此方法查看上一次保存的是什么语言 public void setLanguage() { //根据读取到存放在sp里面的数据 进行设置 Configuration configuration = getResources().getConfiguration(); SharedPreferences sharedPreferences = getSharedPrefer

  • react-intl实现React国际化多语言的方法

    本文主要介绍了react-intl实现React国际化多语言的方法,分享给大家,具体如下: 效果预览 React Intl 国际化步骤 创建国际化资源文件 根据语言获取国际化资源 引入 react-intl 的 local data 创建 LocaleProvider 国际化上下文组件 创建 react-intl 国际化上下文组件 使用 react-intl's components & apis,进行国际化开发 1. 创建国际化资源文件 目前我们管理资源文件的方式是在 src/locales

  • Android NDK开发(C语言基本数据类型)

    目录 1.C 语言包含的数据类型 2.C语言的基本数据类型 3.示例代码 1.C 语言包含的数据类型 如下图所示: 2.C语言的基本数据类型 short.int.long.char.float.double 这六个关键字代表C 语言里的六种基本数据类型. 格式化输出的时候: int %d short %d long %ld float %f double %lf char %c %x 十六进制 %o 八进制 %s 字符串 %p一般以十六进制整数方式输出指针的值,附加前缀0x 在32 位的系统上s

  • Android NDK开发(C语言-文件读写)

    目录 1.文件读写 1.1打开文件 1.2关闭文件 1.3读取文件 1.4写入文件 1.5读写二进制I/O文件 1.6获取文件的大小 1.7文本简单加密.解密 1.8二进制文件简单加解密 1.文件读写 一个文件,无论它是文本文件还是二进制文件,都是代表了一系列的字节.C 语言不仅提供了访问顶层的函数,也提供了底层(OS)调用来处理存储设备上的文件. 1.1打开文件 我们可以使用 fopen( ) 函数来创建一个新的文件或者打开一个已有的文件,这个调用会初始化类型 FILE 的一个对象,类型 FI

  • Android NDK开发(C语言--联合体与枚举)

    目录 1.联合体 1.1定义共用体 1.2共用体占用的内存应足够存储共用体中最大的成员. 1.3联合变量任何时刻只有一个变量存在,最后一次赋值有效 1.4JNI头文件中的联合体 2.枚举 1.联合体 共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型.您可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值.共用体提供了一种使用相同的内存位置的有效方式. 1.1定义共用体 为了定义共用体,您必须使用 union 语句,方式与定义结构类似.union 语句定义了一个新的

  • Android NDK开发(C语言字符串)

    目录 1.C语音的字符串有两种 1.1字符数组 1.2字符指针 2.字符串常用的方法 2.1strcpy字符串拼接 2.2strchr字符串中查找字符 2.3strchr字符串中查找字符 2.4更多用法... 1.C语音的字符串有两种 1.1字符数组 数组可以修改其中某一个值,不可以整体赋值. #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <Windows.h&g

  • Android NDK开发(C语言--动态内存分配)

    1.C 内存管理函数 C 语言为内存的分配和管理提供了几个函数.这些函数可以在 <stdlib.h> 头文件中找到. 序号 函数和描述 1 void calloc(int num, int size); 在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0.所以它的结果是分配了 numsize 个字节长度的内存空间,并且每个字节的值都是0. 2 void free(void *address); 该函数释放 address 所指向的内存块,释放的是动态分配的

  • 网站国际化多语言处理工具i18n安装使用方法图文详解

    目录 一.首先安装i18n 二.创建语言包文件 三.main.js引入i18n 四.修改App.vue文件 五.页面使用 接下来继续完善,加上切换语言按钮 最后 使用方法,按照上图1234顺序即可 总结 一.首先安装i18n npm install --save vue-i18n 此时安装的是vue-i18n最新版本,项目跑不起来,后来换成8.27.1版本就好了 npm install --save vue-i18n@8.27.1 二.创建语言包文件 1.在src目录下创建i18n文件夹 2.在

随机推荐