重写getResources()禁止字体随系统缩放后出现ProgressBar崩溃如何解决
崩溃根源分析
- 你在Activity重写的
getResources()方法中调用了config.setToDefaults(),该方法在Android 7.0及以下系统、部分厂商定制ROM中会直接将locale字段置为null,而非保留系统当前合法的语言配置。ProgressBar加载系统默认样式时需要读取配置中的locale做适配,拿到空值就会触发空指针崩溃。 - 你同时在Activity重写getResources、Fragment重写attachBaseContext,两处配置修改逻辑存在重复冲突,在ViewPager预加载Fragment等场景下会导致配置对象多次修改后状态异常,进一步放大locale为空的问题。
修复方案
1. 优化Activity的getResources()重写逻辑
不要调用setToDefaults()重置全部配置,仅修改你需要的fontScale字段即可,其余配置保留系统原有合法值:
@Override public Resources getResources() { Resources resources = super.getResources(); // 仅当fontScale不为1时才修改,避免不必要的配置重建 if (resources.getConfiguration().fontScale != 1f) { // 新建Configuration副本修改,不要直接修改原Resources携带的配置,避免影响系统逻辑 Configuration config = new Configuration(resources.getConfiguration()); config.fontScale = 1f; return createConfigurationContext(config).getResources(); } return resources; }
2. 移除Fragment中的重复重写逻辑
Activity的Context是Fragment Context的父容器,只要Activity的Resources配置已经固定fontScale为1,Fragment不需要再单独重写attachBaseContext,重复修改反而容易出现配置冲突。如果确实需要单独适配Fragment,也采用仅修改fontScale的逻辑:
@Override protected void attachBaseContext(Context newBase) { Configuration config = new Configuration(newBase.getResources().getConfiguration()); if (config.fontScale != 1f) { config.fontScale = 1f; Context context = newBase.createConfigurationContext(config); super.attachBaseContext(context); } else { super.attachBaseContext(newBase); } }
3. 低版本兼容补充(可选)
如果需要兼容Android 6.0及以下版本,可以在修改配置后增加locale合法性校验:
// 确保locale不为空 if (config.locale == null) { config.locale = Locale.getDefault(); } // Android 7.0及以上多语言场景兼容 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (config.getLocales().isEmpty()) { config.setLocales(LocaleList.getDefault()); } }
内容的提问来源于stack exchange,提问作者yyyy
相关产品推荐
相关产品推荐

