总结安卓Preference使用过程中注意的问题

近期在做新项目中接触到了Preference,这是一种用户界面元素,用于存储和展示应用程序的各种设置和用户偏好。该控件几年前google就已经发布了只是一直没机会应用,其实用起来还是挺方便的,使用过程中遇到了几个问题在此记录下。

1、自定义Preference在屏幕显示时宽度没有充满屏幕

java 复制代码
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相关页面出现闪退

java 复制代码
<Preference
        app:fragment="aaa.bbb.ccc.fragment.DemoFragment"
        app:title="@string/settings_adblock" />

如果在xml你通过fragment属性配置了跳转页面的话,闪退问题是混淆导致的,最好是将fragment属性指定的fragment放到同一个文件夹下,然后配置整个目录不被混淆

java 复制代码
-keep class aaa.bbb.ccc.fragment.**{*;}

3、顶部返回按钮回退处理

通常我们在父Activity里实现PreferenceFragmentCompat.OnPreferenceStartFragmentCallback来监听onPreferenceStartFragment回调,然后获取要打开的fragment添加到布局中

java 复制代码
    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的返回键处理

java 复制代码
findViewById<ImageView>(R.id.setting_page_title).setOnClickListener {
			//如果直接finish的话,无论你fragment层级有多深都会全部关闭
			//popBackStackImmediate从回退栈中弹出当前fragment,弹出成功会返回true
			//如果是到达了父容器层级时会返回false,这时候直接finish即可
            if (!supportFragmentManager.popBackStackImmediate()) {
                finish()
            }
        }

最后总结下自定义Preference的使用

java 复制代码
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
       //对控件进行赋值等操作
    }
}
相关推荐
天花板之恋13 小时前
Compose状态管理
android jetpack
alexhilton1 天前
面向开发者的系统设计:像建筑师一样思考
android·kotlin·android jetpack
Lei活在当下2 天前
【业务场景架构实战】4. 支付状态分层流转的设计和实现
架构·android jetpack·响应式设计
天花板之恋3 天前
Compose之图片加载显示
android jetpack
消失的旧时光-19433 天前
Kotlinx.serialization 使用讲解
android·数据结构·android jetpack
Tans54 天前
Androidx Fragment 源码阅读笔记(下)
android jetpack·源码阅读
Lei活在当下5 天前
【业务场景架构实战】2. 对聚合支付 SDK 的封装
架构·android jetpack
Tans57 天前
Androidx Fragment 源码阅读笔记(上)
android jetpack·源码阅读
alexhilton8 天前
runBlocking实践:哪里该使用,哪里不该用
android·kotlin·android jetpack
Tans511 天前
Androidx Lifecycle 源码阅读笔记
android·android jetpack·源码阅读