Preference源码分析

目录

1、Preference说明

2、Preference支持的属性

3、Preference默认布局


1、Preference说明

文件位置:frameworks/base/core/java/android/preference/Preference.java
大部分情况使用的是androidx包:androidx.preference.Preference
可以build.gradle中引用implementation 'androidx.preference:preference:1.2.0'
/**
 * The basic building block that represents an individual setting displayed to a user in the
 * preference hierarchy. This class provides the data that will be displayed to the user and has
 * a reference to the {@link SharedPreferences} or {@link PreferenceDataStore} instance that
 * persists the preference's values.

以上为源码注释,意思大概是说该构件可以用于偏好设置,并且可以自动使用SharedPreference保存,Android Settings模块的菜单基本上都继承自Preference。

2、Preference支持的属性

这些属性都是可以在xml中进行配置的,支持哪些属性可以在attrs.xml文件中查看<declare-styleable name="Preference">。并在Preference.java中查看解析

* @attr name android:icon 图标
* @attr name android:key  保存设置值的时候就是用的key
* @attr name android:title  标题
* @attr name android:summary   描述
* @attr name android:order   排序,可以通过设置该值来设置菜单排列顺序,数字越小越靠前
* @attr name android:fragment  点击后跳转的Fragment
* @attr name android:layout   自定义layout
* @attr name android:widgetLayout    自定义widge控件,设为0时隐藏,比如点击进入的箭头可以设置这个widgetLayout
* @attr name android:enabled    是否可以点击
* @attr name android:selectable   是否可以选择
* @attr name android:dependency    依赖选项,当依赖选项不可用时,当前选项也不可用
* @attr name android:persistent    是否使用SharedPreference自动保存值
* @attr name android:defaultValue   默认值,即默认是否勾选
* @attr name android:shouldDisableView   设为true时,控件disable时不显示该控件
* @attr name android:singleLineTitle    标题单行显示
* @attr name android:iconSpaceReserved   没有设置icon时,是否预留位置

ps:在Settings中有一些扩展,可查看Settings模块的attrs.xml文件:

<!-- For Search -->
<declare-styleable name="Preference">
    <!-- Synonyms for search results -->
    <attr name="keywords" format="string" />
    <!-- Whether or not the preference is searchable, by default it's true. -->
    <attr name="searchable" format="boolean" />
    <!-- Classname of a PreferenceController corresponding to the preference -->
    <attr name="controller" format="string" />
    <!-- Customized subtitle if it's an unavailable slice -->
    <attr name="unavailableSliceSubtitle" format="string" />
    <!-- Whether or not the preference is for work profile, by default it's false. -->
    <attr name="forWork" format="boolean" />
    <!-- Identifier for highlighting the menu preference on 2-pane -->
    <attr name="highlightableMenuKey" format="string" />
</declare-styleable>

3、Preference默认布局

看Preferece.java源码,private int mLayoutResId = R.layout.preference;
mLayoutResId = TypedArrayUtils.getResourceId(a, R.styleable.Preference_layout,
        R.styleable.Preference_android_layout, R.layout.preference);

说明默认布局为:preference.xml

自定义Preference时需要在构造函数中使用setLayoutResource替换该布局文件

系统源码默认位置为frameworks/base/core/res/res/layout/preference.xml和androidx中的文件基本一致,稍微有点区别,以下为androidx中的源码

<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2015 The Android Open Source Project
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License
  -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:gravity="center_vertical"
    android:paddingEnd="?android:attr/scrollbarSize"
    android:paddingRight="?android:attr/scrollbarSize"
    android:background="?android:attr/selectableItemBackground">

    <FrameLayout
        android:id="@+id/icon_frame"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

<!--此处为icon布局-->
        <androidx.preference.internal.PreferenceImageView
            android:id="@android:id/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:maxWidth="48dp"
            app:maxHeight="48dp" />
    </FrameLayout>

    <RelativeLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="15dip"
        android:layout_marginLeft="15dip"
        android:layout_marginEnd="6dip"
        android:layout_marginRight="6dip"
        android:layout_marginTop="6dip"
        android:layout_marginBottom="6dip"
        android:layout_weight="1">

<!--title标题-->

        <TextView android:id="@android:id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:singleLine="true"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textColor="?android:attr/textColorPrimary"
            android:ellipsize="marquee"
            android:fadingEdge="horizontal" />

<!--summary-->

        <TextView android:id="@android:id/summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@android:id/title"
            android:layout_alignStart="@android:id/title"
            android:layout_alignLeft="@android:id/title"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textColor="?android:attr/textColorSecondary"
            android:maxLines="4" />

    </RelativeLayout>

<!--对应的是

mWidgetLayoutResId--》

    <!-- Preference should place its actual preference widget here. -->
    <LinearLayout android:id="@android:id/widget_frame"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:orientation="vertical" />

</LinearLayout>

4、如何操作Preference子控件

PreferenceGroupAdapter.java中有以下源码,所以自定义Preference覆盖该方法,可以获取到holder
@Override
public void onBindViewHolder(@NonNull PreferenceViewHolder holder, int position) {
    final Preference preference = getItem(position);
    holder.resetState();
    preference.onBindViewHolder(holder);
}
使用示例:

可以修改标题颜色

@Override
public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
    super.onBindViewHolder(holder);
    TextView titleView = (TextView) holder.findViewById(android.R.id.title);
    titleView.setTextColor(mContext.getColor(R.color.personal_default_title_color));
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值