Android多语言适配一般默认是values/drawable目录下的文件是英文语言的资源,如果在中文下使用不同的资源则需要新建values-zh/drawable-zh-xxxdpi这样,res目录下的命名规则是drawable-语言-国家-xxxdpi,在没有特定国家的资源会先找语言相关的目录。但是中文有点特别!这也是一个坑,按常规思维drawable-zh应该是简体中文/繁体中文共有的资源,就是如果没有drawable-zh-rTw或drawable-zh-rHK的资源的话当切到繁体中文时会去drawable-zh查找资源,这样想是大错特错,实际的结果是没有繁体资源时系统会去默认的目录下查找,也就是在drawable或drawable-xxxdpi这些目录找,这个是android的bug还是故意认为HK和TW不是我大中华的?

废话不多话说,实际开发过程中会有这样的需求,就是希望所有的中文不管是繁体还是简体都是共用资源的,根据上面说的规则,如果不分别在zh-rTW和zh-rHK都放入资源的话是不可能做到了,那如果还是想省点资源怎么办呢?下面就是说说图片资源如何做到这点,这里关键要了解android资源的实现,android资源像ImageView查找资源是通过Resources来操作的,来看ImageView查找图片时的关键函数:

 private void resolveUri() {    if (mDrawable != null) {        return;    }    if (getResources() == null) {        return;    }    Drawable d = null;    if (mResource != 0) {        try {            // 关键的地方            d = mContext.getDrawable(mResource);        } catch (Exception e) {            Log.w(LOG_TAG, "Unable to find resource: " + mResource, e);            // Don't try again.            mResource = 0;        }    } else if (mUri != null) {        d = getDrawableFromUri(mUri);        if (d == null) {            Log.w(LOG_TAG, "resolveUri failed on bad bitmap uri: " + mUri);            // Don't try again.            mUri = null;        }    } else {        return;    }}        updateDrawable(d);    }

可以知道关键的地方是能过context.getDrawable来拿到的,如果我们能重写这个函数是不是就可以搞定了?答案是不能,因为这个函数是final不能被重写的,实现如下:

public final Drawable getDrawable(@DrawableRes int id) {    return getResources().getDrawable(id, getTheme());}

能怎么办呢,答案就从上面getDrawable函数的实现找到,getDrawable是能过getResources().getDrawable来实现的,如果能重写getResources,在这里判断是否是繁体,如果是则去zh目录下查找资源,来看getResources的实现:

// Context.javapublic abstract Resources getResources();

看到这里,你应该知道这个思路是可以的!于是按思中路实现,首先判断是否是繁体,然后去默认中文目录下查找

第一步:

判断是用什么语言和国家可以用resources获取config

Locale locale = context.getResources().getConfiguration().locale;if (locale.getLanguage().equals("zh") && !locale.getCountry().equals("CN")) {// 繁体中文}

第二步:

去中文目录查找,首先得有一个中文的resources,当前activity的resources是繁体的,是不能直接调用的,实现方法如下:

private static void updateResource(Resources resource, Locale l) {    Configuration config = resource.getConfiguration();    config.locale = l;    resource.updateConfiguration(config, null);}private static Resources getApplicationResource(PackageManager pm, String pkgName, Locale l) {    Resources resourceForApplication = null;    try {        resourceForApplication = pm.getResourcesForApplication(pkgName);        updateResource(resourceForApplication, l);    } catch (PackageManager.NameNotFoundException e) {    }    return resourceForApplication;}//得到简体中文的resources,由于简体中文没有资源,所以会去默认的中文下去找Resources resources = getApplicationResource(context.getApplicationContext().getPackageManager(),                    context.getPackageName(), new Locale("zh", "CN"));

综合起来是重写Activity的getResources:

@Overridepublic Resources getResources() {    Locale locale = context.getResources().getConfiguration().locale;    if (locale.getLanguage().equals("zh") && !locale.getCountry().equals("CN")) {        // 繁体中文        Resources resources = getApplicationResource(context.getApplicationContext().getPackageManager(),                    context.getPackageName(), new Locale("zh", "CN"));        if (resources != null) {            return resources;        }    }    return super.getResources();}

这样就实现了所有中文上都共用一套资源!上面的示例在xml中指定资源或者在代码里getDrawable可以这么使用,如果是用第三方图片加载库怎么实现?这里展示一下ImageLoader的实现:
ImageLoader加载资源是默认是通过BaseImageLoader去加载的,加载时会调用BaseDownloader去获取资源,我们只要自定义Downloader就可以了:

public class NotePaperImageDownloader extends BaseImageDownloader {    // 繁体中文时用的resources    Resources mResources;    public NotePaperImageDownloader(Context context) {        super(context);    }    public NotePaperImageDownloader(Context context, int connectTimeout, int readTimeout) {        super(context, connectTimeout, readTimeout);    }    @Override    protected InputStream getStreamFromDrawable(String imageUri, Object extra) {        Locale locale = context.getResources().getConfiguration().locale;        if (locale.getLanguage().equals("zh") && !locale.getCountry().equals("CN")) {            // 繁体中文,使用简体中文的资源进行加载,否则在没有指定繁体资源时默认会去英文下找,会不会去drawable-zh-xx去找          if (mResources == null) {                Resources resources = getApplicationResource(context.getApplicationContext().getPackageManager(),                        context.getPackageName(), new Locale("zh", "CN"));                if (resources == null) {                    return super.getStreamFromDrawable(imageUri, extra);                }                mResources = resources;            }            String drawableIdString = Scheme.DRAWABLE.crop(imageUri);            int drawableId = Integer.parseInt(drawableIdString);            return mResources.openRawResource(drawableId);        } else {            return super.getStreamFromDrawable(imageUri, extra);        }    }}

总结:

关于android资源的加载,只要熟悉资源加载框架context/resources/assetmanger几个关键的类就可以做很多事。

更多相关文章

  1. 理解 ViewStub 原理
  2. Android(安卓)深入理解Loader机制 让APP轻装上阵
  3. Android:资源 id 及资源 id 的动态获取
  4. 安卓系统的启动流程
  5. android TextView设置中文字体加粗实现方法
  6. Android(安卓)项目中文件夹作用(res文件夹详细介绍)
  7. android中URI简介
  8. Android中多媒体处理
  9. android全平台编译libjpeg-turbo并基于ANativeWindow加载JPEG图

随机推荐

  1. 关于Android用户定位获取location值为nul
  2. 【Android(安卓)开发教程】PreferenceFra
  3. Android中获取网络图片的方法(如果手机缓
  4. Android(安卓)Butterknife 8.4.0 使用方
  5. Android学习笔记之cyanogenmod编译篇
  6. ubuntu12.04 android studio 安装(装完后
  7. 实现Android(安卓)ListView 自动加载更多
  8. ionic中android,和ios生成的一些兼容问题-
  9. Android(安卓)TTS学习——保存对你的喜欢
  10. Android安装应用后点击,打开.(Open)带来