Android如何动态调整应用字体大小详解
前言
Android应用的字体大小默认随系统设置变化,但有时我们希望自主控制应用的字体大小,例如微信等应用,本文将详细介绍如何通过修改fontScale
实现这一目标。
一、为什么要动态设置字体大小?
由于项目面对的是中老年客户,项目中自带的字体无法满足客户需求,需要提供一种方法来动态调整应用字体的大小,以便更好地适应用户的视力需求。
二、核心原理
Android应用中的字体大小变化是由android.content.res.Configuration
类中的fontScale
控制的,要使应用字体大小不随系统设置变化而由我们自主控制,就需要修改fontScale
为我们自己设置的数值。
三、实现步骤
1. 在Application中进行初始化
我们需要在Application
类中进行一些初始化操作,包括获取SharedPreferences
和注册ActivityLifecycleCallbacks
。
public class MainApplication extends Application implements Application.ActivityLifecycleCallbacks { private List<Activity> activityList; private float fontScale; private SharedPreferences preferences; private static MainApplication mainApplication; @Override public void onCreate() { super.onCreate(); init(); } private void init() { mainApplication = this; preferences = PreferenceManager.getDefaultSharedPreferences(this); fontScale = getFontScale(); registerActivityLifecycleCallbacks(this); } public static float getFontScale() { float fontScale = 1.0f; if (mainApplication != null) { fontScale = mainApplication.preferences.getFloat("fontScale", 1.0f); } return fontScale; } @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { if (activityList == null) { activityList = new ArrayList<>(); } // 禁止字体大小随系统设置变化 Resources resources = activity.getResources(); if (resources != null && resources.getConfiguration().fontScale != fontScale) { android.content.res.Configuration configuration = resources.getConfiguration(); configuration.fontScale = fontScale; resources.updateConfiguration(configuration, resources.getDisplayMetrics()); } activityList.add(activity); } @Override public void onActivityStarted(Activity activity) {} @Override public void onActivityResumed(Activity activity) {} @Override public void onActivityPaused(Activity activity) {} @Override public void onActivityStopped(Activity activity) {} @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {} @Override public void onActivityDestroyed(Activity activity) { if (activityList != null) { activityList.remove(activity); } } public static void setAppFontSize(float fontScale) { if (mainApplication != null) { List<Activity> activityList = mainApplication.activityList; if (activityList != null) { for (Activity activity : activityList) { if (activity instanceof SettingActivity) { continue; } Resources resources = activity.getResources(); if (resources != null) { android.content.res.Configuration configuration = resources.getConfiguration(); configuration.fontScale = fontScale; resources.updateConfiguration(configuration, resources.getDisplayMetrics()); activity.recreate(); if (fontScale != mainApplication.fontScale) { mainApplication.fontScale = fontScale; mainApplication.preferences.edit().putFloat("fontScale", fontScale).apply(); } } } } } }}
2. 重写getResources
方法
为了确保在所有API级别上都能正常工作,我们需要重写getResources
方法,对于API级别小于25的设备,我们在BaseActivity
中重写getResources
方法;对于API级别大于等于25的设备,我们在attachBaseContext
方法中进行处理。
public class BaseActivity extends AppCompatActivity { @Override public Resources getResources() { Resources res = super.getResources(); if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) { Configuration config = res.getConfiguration(); config.fontScale = MyApplication.getFontSize(); // 设置正常字体大小的倍数 res.updateConfiguration(config, res.getDisplayMetrics()); } return res; } @Override protected void attachBaseContext(Context newBase) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { final Resources res = newBase.getResources(); final Configuration config = res.getConfiguration(); config.fontScale = MyApplication.getFontSize(); // 设置正常字体大小的倍数 final Context newContext = newBase.createConfigurationContext(config); super.attachBaseContext(newContext); } else { super.attachBaseContext(newBase); } }}
动态调整字体大小的方法
提供一个静态方法setAppFontSize
,用于动态调整应用的字体大小,该方法会遍历所有已创建的活动,并更新它们的fontScale
值。
public static void setAppFontSize(float fontScale) { if (mainApplication != null) { List<Activity> activityList = mainApplication.activityList; if (activityList != null) { for (Activity activity : activityList) { if (activity instanceof SettingActivity) { continue; } Resources resources = activity.getResources(); if (resources != null) { android.content.res.Configuration configuration = resources.getConfiguration(); configuration.fontScale = fontScale; resources.updateConfiguration(configuration, resources.getDisplayMetrics()); activity.recreate(); if (fontScale != mainApplication.fontScale) { mainApplication.fontScale = fontScale; mainApplication.preferences.edit().putFloat("fontScale", fontScale).apply(); } } } } }}
四、归纳
通过上述步骤,我们可以实现Android应用字体大小的动态调整,使其不依赖于系统设置,这样,我们就可以根据用户需求灵活地调整应用的字体大小,提高用户体验。