近期在做新项目中接触到了Preference,这是一种用户界面元素,用于存储和展示应用程序的各种设置和用户偏好。该控件几年前google就已经发布了只是一直没机会应用,其实用起来还是挺方便的,使用过程中遇到了几个问题在此记录下。
1、自定义Preference在屏幕显示时宽度没有充满屏幕
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr) {
//主要是这个点需要调用setLayoutResource而不是setWidgetLayoutResource
layoutResource = R.layout.preference_icon_title_layout
val config = context.obtainStyledAttributes(
attrs,
R.styleable.IconTitlePreference,
defStyleAttr,
defStyleRes
)
//获取属性
mTitle = config.getString(R.styleable.IconTitlePreference_settingTitle)
config.recycle()
}
2、release包打开Preference相关页面出现闪退
<Preference
app:fragment="aaa.bbb.ccc.fragment.DemoFragment"
app:title="@string/settings_adblock" />
如果在xml你通过fragment属性配置了跳转页面的话,闪退问题是混淆导致的,最好是将fragment属性指定的fragment放到同一个文件夹下,然后配置整个目录不被混淆
-keep class aaa.bbb.ccc.fragment.**{*;}
3、顶部返回按钮回退处理
通常我们在父Activity里实现PreferenceFragmentCompat.OnPreferenceStartFragmentCallback来监听onPreferenceStartFragment回调,然后获取要打开的fragment添加到布局中
override fun onPreferenceStartFragment(
caller: PreferenceFragmentCompat,
pref: Preference
): Boolean {
val args = pref.extras
val fragment = supportFragmentManager.fragmentFactory.instantiate(
classLoader,
pref.fragment!!
)
fragment.arguments = args
fragment.setTargetFragment(caller, 0)
supportFragmentManager.beginTransaction()
//可以在这里设置fragment启动动画
.setCustomAnimations(
R.anim.slide_in_from_right,
R.anim.fade_out_scale,
R.anim.fade_in_scale,
R.anim.slide_out_to_right
)
.replace(R.id.root, fragment)
//这个方法一定要调用,为了将当前fragment添加到回退栈中,用于下面的popBackStackImmediate调用
.addToBackStack(null)
.commit()
return true
}
顶部title的返回键处理
findViewById<ImageView>(R.id.setting_page_title).setOnClickListener {
//如果直接finish的话,无论你fragment层级有多深都会全部关闭
//popBackStackImmediate从回退栈中弹出当前fragment,弹出成功会返回true
//如果是到达了父容器层级时会返回false,这时候直接finish即可
if (!supportFragmentManager.popBackStackImmediate()) {
finish()
}
}
最后总结下自定义Preference的使用
class SuperPreference : Preference {
private var mTitle : String?
private lateinit var mIconIv : ImageView
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(
context,
attrs,
R.attr.preferenceStyle
)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : this(
context,
attrs,
defStyleAttr,
0
)
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr) {
//替换布局
layoutResource = R.layout.preference_icon_title_layout
val config = context.obtainStyledAttributes(
attrs,
//自定义的属性
R.styleable.IconTitlePreference,
defStyleAttr,
defStyleRes
)
//获取属性
mTitle = config.getString(R.styleable.IconTitlePreference_settingTitle)
config.recycle()
}
override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
//在这里对控件的findViewById初始化操作
mIconIv = holder.findViewById(R.id.setting_icon) as ImageView
//对控件进行赋值等操作
}
}