Kotlin中自定义PreferenceScreen与SettingsFragment管理的两类问题求助
Android自定义Preference踩坑解决:布局显示异常+继承类问题
一、自定义Preference布局显示异常
问题情况
把switch_preference_layout.xml用android:widgetLayout加到Preference标签里,布局几乎看不见;换成android:layout直接就没了。
为啥会这样
android:widgetLayout是用来指定Preference右侧小控件的布局,这个区域的尺寸被Preference默认布局限制死了,要是你的自定义布局没设合适的宽高,或者内部控件没适配,就会缩成一团几乎看不见。android:layout根本不是Preference标签能用的属性,系统不认这个,设置了自然就显示不出来。
解决办法
- 要是想自定义整个Preference的布局,别用
android:layout,改用android:layoutResource,示例代码:
<Preference android:key="custom_switch_pref" android:title="自定义开关设置" android:layoutResource="@layout/switch_preference_layout" />
- 检查你的
switch_preference_layout.xml,根布局宽高设成match_parent,内部控件用系统预设的id(比如@android:id/title、@android:id/summary),这样Preference能自动绑定内容,示例布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="16dp" android:gravity="center_vertical"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical"> <TextView android:id="@android:id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="16sp" android:textColor="?android:textColorPrimary" /> <TextView android:id="@android:id/summary" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="14sp" android:textColor="?android:textColorSecondary" android:layout_marginTop="4dp" /> </LinearLayout> <Switch android:id="@android:id/widget_frame" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
- 要是只改右侧的开关控件,用
android:widgetLayout时,布局根宽高设wrap_content,内部开关正常设置尺寸就行,示例:
<!-- switch_widget_layout.xml --> <Switch xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="8dp" />
然后在Preference里引用:
<Preference android:key="right_switch_pref" android:title="右侧自定义开关" android:widgetLayout="@layout/switch_widget_layout" />
二、Preference继承类的构造参数与方法重写问题
问题情况
继承Preference的时候,必须传Context当构造参数(和参考示例不一样);想重写isVisible方法,IDE说这个方法是final不能改,删掉重写代码又提示必须重写。
为啥会这样
- 不同Android SDK版本里,Preference的构造方法变过,新版本要求必须带Context的构造方法,不然初始化不了,老版本的示例可能没这个要求。
isVisible在新版AndroidX Preference库已经被标成final了,不能重写,参考示例可能用的是旧版Support库,所以有差异。IDE提示必须重写大概率是误判,或者你不小心继承了抽象类,其实isVisible不是抽象方法。
解决办法
- 把Preference的构造方法都覆盖了,适配不同初始化场景,Java代码示例:
public class CustomPreference extends Preference { public CustomPreference(Context context) { super(context); init(); } public CustomPreference(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CustomPreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } public CustomPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(); } private void init() { // 这里写初始化逻辑,比如设置布局、加监听 } }
Kotlin版本:
class CustomPreference @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = androidx.preference.R.attr.preferenceStyle, defStyleRes: Int = 0 ) : Preference(context, attrs, defStyleAttr, defStyleRes) { init { // 初始化操作 } }
- 关于
isVisible:既然不能重写,要控制显示状态就用setVisible(boolean)动态设置,或者重写onBindViewHolder方法,绑定视图的时候控制显示,示例:
@Override public void onBindViewHolder(PreferenceViewHolder holder) { super.onBindViewHolder(holder); // 自己写判断逻辑,决定显示还是隐藏 boolean show = shouldDisplay(); holder.itemView.setVisibility(show ? View.VISIBLE : View.GONE); } private boolean shouldDisplay() { // 这里放你的判断条件 return true; }
要是IDE还瞎提示必须重写isVisible,就清理下缓存(Android Studio里点File -> Invalidate Caches / Restart),或者检查是不是继承错了类。
内容的提问来源于stack exchange,提问作者Cody Correll
相关产品推荐
相关产品推荐

