You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动