目录
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)); }