Android Kotlin中Switch控件fontFamily设置失效问题求助
解决Switch控件自定义字体不生效的问题
核心原因
原生Switch的switchTextAppearance样式对fontFamily属性的支持存在局限,系统控件的文本绘制逻辑会忽略该属性,导致自定义字体无法生效,而textSize、textColor等基础属性不受此限制。
可行解决方案
方案1:改用SwitchCompat(推荐)
androidx.appcompat.widget.SwitchCompat对自定义样式的兼容性更好,能正常识别switchTextAppearance中的字体设置:
- 替换布局中的原生
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" />
- 调整样式的父类,确保继承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
相关产品推荐
相关产品推荐

