You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin中Switch控件fontFamily设置失效问题求助

解决Switch控件自定义字体不生效的问题

核心原因

原生Switch的switchTextAppearance样式对fontFamily属性的支持存在局限,系统控件的文本绘制逻辑会忽略该属性,导致自定义字体无法生效,而textSize、textColor等基础属性不受此限制。

可行解决方案

方案1:改用SwitchCompat(推荐)

androidx.appcompat.widget.SwitchCompat对自定义样式的兼容性更好,能正常识别switchTextAppearance中的字体设置:

  1. 替换布局中的原生Switch:
<androidx.appcompat.widget.SwitchCompat
    android:id="@+id/switch1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="256dp"
    android:showText="true"
    android:checked="true"
    android:textOff="خاموش"
    android:textOn="روشن"
    app:switchTextAppearance="@style/MyStyle"
    android:thumb="@drawable/thumb"
    android:track="@drawable/track"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
  1. 调整样式的父类,确保继承AppCompat文本样式:
<style name="MyStyle" parent="TextAppearance.AppCompat">
    <item name="android:textColor">@color/black</item>
    <item name="android:textSize">29sp</item>
    <item name="android:textStyle">bold</item>
    <item name="android:fontFamily">@font/iransans</item>
    <item name="fontFamily">@font/iransans</item>
</style>

方案2:代码动态设置字体

如果必须使用原生Switch,可通过代码直接为控件的文本子视图设置字体:

val switch1 = findViewById<Switch>(R.id.switch1)
val iranSansFont = ResourcesCompat.getFont(this, R.font.iransans)

// 遍历Switch的子视图,为TextView设置字体
switch1.children.forEach { view ->
    if (view is TextView) {
        view.typeface = iranSansFont
    }
}

或者用反射更精准地获取开关的文本控件:

val switch1 = findViewById<Switch>(R.id.switch1)
try {
    // 获取开启状态的文本视图
    val textOnField = Switch::class.java.getDeclaredField("mTextOn")
    textOnField.isAccessible = true
    (textOnField.get(switch1) as TextView).typeface = ResourcesCompat.getFont(this, R.font.iransans)

    // 获取关闭状态的文本视图
    val textOffField = Switch::class.java.getDeclaredField("mTextOff")
    textOffField.isAccessible = true
    (textOffField.get(switch1) as TextView).typeface = ResourcesCompat.getFont(this, R.font.iransans)
} catch (e: Exception) {
    e.printStackTrace()
}

方案3:自定义Switch控件

创建自定义Switch类,重写绘制逻辑强制使用指定字体:

class CustomSwitch @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : Switch(context, attrs, defStyleAttr) {

    private var customTypeface: Typeface? = null

    init {
        val ta = context.obtainStyledAttributes(attrs, R.styleable.CustomSwitch)
        val fontResId = ta.getResourceId(R.styleable.CustomSwitch_customFont, -1)
        if (fontResId != -1) {
            customTypeface = ResourcesCompat.getFont(context, fontResId)
        }
        ta.recycle()
    }

    override fun onDraw(canvas: Canvas?) {
        customTypeface?.let {
            paint.typeface = it
            textOn?.let { setTextOn(textOn) }
            textOff?.let { setTextOff(textOff) }
        }
        super.onDraw(canvas)
    }
}

在res/values/attrs.xml中添加自定义属性:

<declare-styleable name="CustomSwitch">
    <attr name="customFont" format="reference" />
</declare-styleable>

布局中使用自定义控件:

<com.yourpackage.CustomSwitch
    android:id="@+id/switch1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="256dp"
    android:showText="true"
    android:checked="true"
    android:textOff="خاموش"
    android:textOn="روشن"
    android:switchTextAppearance="@style/MyStyle"
    app:customFont="@font/iransans"
    android:thumb="@drawable/thumb"
    android:track="@drawable/track"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

内容的提问来源于stack exchange,提问作者Amir Elahi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 03:00:04