Android偏好设置:实现用户自定义字体大小功能
实现应用字体大小自定义功能的完整指南
我来一步步帮你实现这个字体大小选择功能,和Jota+这类应用的逻辑基本一致,跟着下面的步骤来就行:
1. 先在偏好设置XML里添加字体大小选择项
首先要给你的pref_main.xml加上一个ListPreference,让用户能从预设的选项里挑字体大小。示例代码如下:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 保留你已有的其他偏好设置项 --> <ListPreference android:key="font_size_key" android:title="字体大小" android:summary="调整应用内所有文字的显示大小" android:entries="@array/font_size_display_options" android:entryValues="@array/font_size_value_options" android:defaultValue="medium" /> </PreferenceScreen>
然后在res/values/arrays.xml里创建对应的字符串数组(如果没有这个文件就新建一个):
<resources> <string-array name="font_size_display_options"> <item>小号</item> <item>默认</item> <item>大号</item> <item>超大号</item> </string-array> <string-array name="font_size_value_options"> <item>0.8</item> <item>1.0</item> <item>1.2</item> <item>1.5</item> </string-array> </resources>
这里把值设为缩放比例,后面用起来更方便~
2. 监听偏好设置的变化
在你的PreferenceFragment里,需要监听用户的选择变化,这样修改后能立刻让应用生效。代码可以这么写:
public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener { @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.pref_main, rootKey); // 注册偏好变化监听 getPreferenceManager().getSharedPreferences() .registerOnSharedPreferenceChangeListener(this); // 可选:设置当前选中项的摘要,让用户直观看到当前选择 ListPreference fontSizePref = findPreference("font_size_key"); if (fontSizePref != null) { int selectedIndex = fontSizePref.findIndexOfValue(fontSizePref.getValue()); fontSizePref.setSummary(fontSizePref.getEntries()[selectedIndex]); // 监听选择变化,实时更新摘要 fontSizePref.setOnPreferenceChangeListener((preference, newValue) -> { int index = ((ListPreference) preference).findIndexOfValue((String) newValue); preference.setSummary(((ListPreference) preference).getEntries()[index]); return true; }); } } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if ("font_size_key".equals(key)) { // 发送广播通知所有页面更新字体大小 Intent updateIntent = new Intent("ACTION_FONT_SIZE_UPDATED"); requireActivity().sendBroadcast(updateIntent); } } @Override public void onDestroy() { super.onDestroy(); // 记得取消注册,避免内存泄漏 getPreferenceManager().getSharedPreferences() .unregisterOnSharedPreferenceChangeListener(this); } }
3. 在应用页面中应用字体大小
接下来要让所有需要调整字体的页面响应这个设置。可以先写一个工具类来统一处理缩放逻辑:
public class FontScaleHelper { public static float getFontScale(Context context) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); String scaleStr = prefs.getString("font_size_key", "1.0"); return Float.parseFloat(scaleStr); } // 给单个TextView设置缩放后的字体大小 public static void applyFontScale(TextView textView, Context context) { float originalSize = textView.getTextSize(); float scale = getFontScale(context); textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, originalSize * scale); } }
然后在你的主Activity(或者BaseActivity,方便所有页面复用)里注册广播接收器,接收字体变化的通知并更新:
public class MainActivity extends AppCompatActivity { private BroadcastReceiver fontUpdateReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化广播接收器 fontUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { updateAllFontSizes(); } }; registerReceiver(fontUpdateReceiver, new IntentFilter("ACTION_FONT_SIZE_UPDATED")); // 页面创建时先应用一次字体设置 updateAllFontSizes(); } private void updateAllFontSizes() { // 找到所有需要调整的TextView,逐个应用缩放 TextView tvItemName = findViewById(R.id.tv_item_name); TextView tvItemDesc = findViewById(R.id.tv_item_desc); // ... 其他TextView FontScaleHelper.applyFontScale(tvItemName, this); FontScaleHelper.applyFontScale(tvItemDesc, this); } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(fontUpdateReceiver); } }
4. 进阶优化(可选)
- 如果你的应用有大量页面,建议创建一个
BaseActivity,把字体更新和广播注册的逻辑放到里面,所有业务页面继承它,不用重复写代码。 - 如果你想让字体大小的变化更平滑,可以避免重启Activity,用上面的广播+实时更新控件的方式,体验更好。
- 要是担心系统字体大小的影响,可以在
applyFontScale方法里先获取原始的dp/sp值,再乘以缩放比例,确保不受系统设置干扰。
这样一套下来,你的应用就能像Jota+一样,让用户在设置里自由切换字体大小啦!
内容的提问来源于stack exchange,提问作者Arthur Meier




