如何在首选项(设置菜单)之间添加分隔线?
How to add divider lines in between preferences (settings menu)?
在我的设置中 我有多个首选项,它们之间没有线条,看起来很丑。我该如何解决这个问题?
我认为您正试图在自定义 preference.xml 中添加分隔线。
如果您同时使用 PreferenceActivity 或 Preference Fragment,应该很容易。
只需转到 onCreate 方法并调用此方法
ListView list = getListView();
list.setDivider(); // pass null for no dividers or a valid drawable for dividers.
以下为AndroidX:
在 AndroidX 中,getListView() returns 一个 RecyclerView。
可以使用 .addItemDecoration() 将分隔线添加到 RecyclerViews
这应该在 RecyclerView 在 onActivityCreated() 中膨胀后完成。
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
RecyclerView recyclerView = getListView();
DividerItemDecoration itemDecoration = new DividerItemDecoration(context, RecyclerView.VERTICAL);
recyclerView.addItemDecoration(itemDecoration);
}
我找到的最合适的解决方案是在 XML 中设置类别和首选项的布局。例如
pref_screen.xml:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Preference
android:key="@string/pref_org_code_key"
android:title="@string/pref_org_code_title"
android:defaultValue="@string/pref_org_code_default"
app:iconSpaceReserved="false"
android:layout="@layout/single_preference" />
<PreferenceCategory android:title="Invitation - Auto accept">
<CheckBoxPreference
android:defaultValue="@bool/friend_invite_accept_default"
android:key="@string/pref_friend_invite_auto_accept_key"
android:summaryOff="@string/pref_disabled"
android:summaryOn="@string/pref_enabled"
android:title="@string/pref_invites_friend_title"
app:iconSpaceReserved="false"
android:layout="@layout/single_preference"
android:widgetLayout="@layout/single_pref_checkbox" />
<CheckBoxPreference
android:defaultValue="@bool/group_invite_accept_default"
android:key="@string/pref_group_invite_auto_accept_key"
android:summaryOff="@string/pref_disabled"
android:summaryOn="@string/pref_enabled"
android:title="@string/pref_invites_group_title"
app:iconSpaceReserved="false"
android:layout="@layout/single_preference"
android:widgetLayout="@layout/single_pref_checkbox" />
</PreferenceCategory>
</PreferenceScreen>
single_preference.xml
<?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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeightSmall">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
android:paddingRight="?android:attr/listPreferredItemPaddingRight"
android:background="?android:attr/selectableItemBackground"
android:clipToPadding="false"
android:focusable="true" >
<LinearLayout
android:id="@+id/icon_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="-4dp"
android:minWidth="60dp"
android:gravity="start|center_vertical"
android:orientation="horizontal"
android:paddingRight="12dp"
android:paddingTop="4dp"
android:paddingBottom="4dp">
<android.support.v7.internal.widget.PreferenceImageView
android:id="@android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:maxWidth="48dp"
app:maxHeight="48dp" />
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<TextView android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="@style/Preference_TextAppearanceMaterialSubhead"
android:ellipsize="marquee" />
<TextView android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignLeft="@android:id/title"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="10" />
</RelativeLayout>
<!-- 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="end|center_vertical"
android:paddingLeft="16dp"
android:orientation="vertical" >
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="@color/cool_grey"/>
</LinearLayout>
single_pref_checkbox.xml
<?xml version="1.0" encoding="utf-8"?>
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+android:id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:clickable="false"
android:background="@null" />
single_pref_category.xml
<?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_marginBottom="0dp"
android:layout_marginTop="0dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="match_parent"
android:layout_height="8dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="@color/grey300"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft">
<LinearLayout
android:id="@+id/icon_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start|center_vertical"
android:orientation="horizontal">
<android.support.v7.internal.widget.PreferenceImageView
android:id="@android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:maxHeight="18dp"
app:maxWidth="18dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="@dimen/preference_category_padding_start">
<TextView
android:id="@android:id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:paddingRight="?android:attr/listPreferredItemPaddingRight"
android:textAlignment="viewStart"
android:textColor="@color/preference_fallback_accent_color"
android:textStyle="bold" />
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="?android:attr/textColorSecondary"/>
</LinearLayout>
</FrameLayout>
</LinearLayout>
也许还需要修改样式并使用此样式而不是默认样式:
<style name="SpecialPreferenceTheme">
<item name="android:scrollbars">vertical</item>
<item name="checkBoxPreferenceStyle">@style/Preference.CheckBoxPreference.Material</item>
<item name="dialogPreferenceStyle">@style/Preference.DialogPreference.Material</item>
<item name="dropdownPreferenceStyle">@style/Preference.DropDown.Material</item>
<item name="editTextPreferenceStyle">@style/Preference.DialogPreference.EditTextPreference.Material</item>
<item name="preferenceCategoryStyle">@style/CategoryPreference</item>
<item name="preferenceFragmentCompatStyle">@style/PreferenceFragment.Material</item>
<item name="preferenceFragmentListStyle">@style/PreferenceFragmentList.Material</item>
<item name="preferenceFragmentStyle">@style/PreferenceFragment.Material</item>
<item name="preferenceScreenStyle">@style/Preference.PreferenceScreen.Material</item>
<item name="preferenceStyle">@style/SinglePreference</item>
<item name="seekBarPreferenceStyle">@style/Preference.SeekBarPreference.Material</item>
<item name="switchPreferenceCompatStyle">@style/Preference.SwitchPreferenceCompat.Material</item>
<item name="switchPreferenceStyle">@style/Preference.SwitchPreference.Material</item>
</style>
<style name="SinglePreference">
<item name="android:layout">@layout/single_preference</item>
<item name="allowDividerAbove">false</item>
<item name="allowDividerBelow">true</item>
<item name="singleLineTitle">false</item>
<item name="iconSpaceReserved">false</item>
</style>
<style name="CategoryPreference">
<item name="android:layout">@layout/single_pref_category</item>
<item name="allowDividerAbove">false</item>
<item name="allowDividerBelow">false</item>
<item name="iconSpaceReserved">false</item>
</style>
<style name="CheckboxPreferece">
<item name="android:layout">@layout/single_preference</item>
<item name="allowDividerAbove">false</item>
<item name="allowDividerBelow">true</item>
<item name="iconSpaceReserved">false</item>
</style>
AndroidX
如果使用 AndroidX,要显示分隔线,您只需在首选项中添加以下属性即可 XML:
<Preference
...
app:allowDividerAbove="true"
app:allowDividerBelow="true"
... />
更详细的答案在这里:
感谢Matthew Smith
的回答。
一个正确的方法是覆盖 PreferenceFragmentCompat
的 onCreateRecyclerView
方法 class
@Override
public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
RecyclerView recyclerView = super.onCreateRecyclerView(inflater, parent, savedInstanceState);
DividerItemDecoration itemDecoration = new DividerItemDecoration(getContext(), RecyclerView.VERTICAL);
recyclerView.addItemDecoration(itemDecoration);
return recyclerView;
}
这适用于 com.android.support:preference-v7:28.0.0
图书馆
在 androidx(基于 )的整个设置屏幕中创建分隔线的一个好方法是创建 Preference 的子类并覆盖 onBindViewHolder,然后在 xml 中使用它。它适用于
implementation 'androidx.preference:preference:1.1.1'
但不幸的是,对于具有多种首选项类型的屏幕来说,这不是一个好的解决方案(可以为 EditTextPreference 等创建子类)
public class CustomPreference extends Preference {
public CustomPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
holder.setDividerAllowedAbove(true);
}
}
在我的设置中
我认为您正试图在自定义 preference.xml 中添加分隔线。
如果您同时使用 PreferenceActivity 或 Preference Fragment,应该很容易。
只需转到 onCreate 方法并调用此方法
ListView list = getListView();
list.setDivider(); // pass null for no dividers or a valid drawable for dividers.
以下为AndroidX:
在 AndroidX 中,getListView() returns 一个 RecyclerView。
可以使用 .addItemDecoration() 将分隔线添加到 RecyclerViews
这应该在 RecyclerView 在 onActivityCreated() 中膨胀后完成。
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
RecyclerView recyclerView = getListView();
DividerItemDecoration itemDecoration = new DividerItemDecoration(context, RecyclerView.VERTICAL);
recyclerView.addItemDecoration(itemDecoration);
}
我找到的最合适的解决方案是在 XML 中设置类别和首选项的布局。例如
pref_screen.xml:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Preference
android:key="@string/pref_org_code_key"
android:title="@string/pref_org_code_title"
android:defaultValue="@string/pref_org_code_default"
app:iconSpaceReserved="false"
android:layout="@layout/single_preference" />
<PreferenceCategory android:title="Invitation - Auto accept">
<CheckBoxPreference
android:defaultValue="@bool/friend_invite_accept_default"
android:key="@string/pref_friend_invite_auto_accept_key"
android:summaryOff="@string/pref_disabled"
android:summaryOn="@string/pref_enabled"
android:title="@string/pref_invites_friend_title"
app:iconSpaceReserved="false"
android:layout="@layout/single_preference"
android:widgetLayout="@layout/single_pref_checkbox" />
<CheckBoxPreference
android:defaultValue="@bool/group_invite_accept_default"
android:key="@string/pref_group_invite_auto_accept_key"
android:summaryOff="@string/pref_disabled"
android:summaryOn="@string/pref_enabled"
android:title="@string/pref_invites_group_title"
app:iconSpaceReserved="false"
android:layout="@layout/single_preference"
android:widgetLayout="@layout/single_pref_checkbox" />
</PreferenceCategory>
</PreferenceScreen>
single_preference.xml
<?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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeightSmall">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
android:paddingRight="?android:attr/listPreferredItemPaddingRight"
android:background="?android:attr/selectableItemBackground"
android:clipToPadding="false"
android:focusable="true" >
<LinearLayout
android:id="@+id/icon_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="-4dp"
android:minWidth="60dp"
android:gravity="start|center_vertical"
android:orientation="horizontal"
android:paddingRight="12dp"
android:paddingTop="4dp"
android:paddingBottom="4dp">
<android.support.v7.internal.widget.PreferenceImageView
android:id="@android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:maxWidth="48dp"
app:maxHeight="48dp" />
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<TextView android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="@style/Preference_TextAppearanceMaterialSubhead"
android:ellipsize="marquee" />
<TextView android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignLeft="@android:id/title"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="10" />
</RelativeLayout>
<!-- 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="end|center_vertical"
android:paddingLeft="16dp"
android:orientation="vertical" >
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="@color/cool_grey"/>
</LinearLayout>
single_pref_checkbox.xml
<?xml version="1.0" encoding="utf-8"?>
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+android:id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:clickable="false"
android:background="@null" />
single_pref_category.xml
<?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_marginBottom="0dp"
android:layout_marginTop="0dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="match_parent"
android:layout_height="8dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="@color/grey300"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft">
<LinearLayout
android:id="@+id/icon_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start|center_vertical"
android:orientation="horizontal">
<android.support.v7.internal.widget.PreferenceImageView
android:id="@android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:maxHeight="18dp"
app:maxWidth="18dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="@dimen/preference_category_padding_start">
<TextView
android:id="@android:id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:paddingRight="?android:attr/listPreferredItemPaddingRight"
android:textAlignment="viewStart"
android:textColor="@color/preference_fallback_accent_color"
android:textStyle="bold" />
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="?android:attr/textColorSecondary"/>
</LinearLayout>
</FrameLayout>
</LinearLayout>
也许还需要修改样式并使用此样式而不是默认样式:
<style name="SpecialPreferenceTheme">
<item name="android:scrollbars">vertical</item>
<item name="checkBoxPreferenceStyle">@style/Preference.CheckBoxPreference.Material</item>
<item name="dialogPreferenceStyle">@style/Preference.DialogPreference.Material</item>
<item name="dropdownPreferenceStyle">@style/Preference.DropDown.Material</item>
<item name="editTextPreferenceStyle">@style/Preference.DialogPreference.EditTextPreference.Material</item>
<item name="preferenceCategoryStyle">@style/CategoryPreference</item>
<item name="preferenceFragmentCompatStyle">@style/PreferenceFragment.Material</item>
<item name="preferenceFragmentListStyle">@style/PreferenceFragmentList.Material</item>
<item name="preferenceFragmentStyle">@style/PreferenceFragment.Material</item>
<item name="preferenceScreenStyle">@style/Preference.PreferenceScreen.Material</item>
<item name="preferenceStyle">@style/SinglePreference</item>
<item name="seekBarPreferenceStyle">@style/Preference.SeekBarPreference.Material</item>
<item name="switchPreferenceCompatStyle">@style/Preference.SwitchPreferenceCompat.Material</item>
<item name="switchPreferenceStyle">@style/Preference.SwitchPreference.Material</item>
</style>
<style name="SinglePreference">
<item name="android:layout">@layout/single_preference</item>
<item name="allowDividerAbove">false</item>
<item name="allowDividerBelow">true</item>
<item name="singleLineTitle">false</item>
<item name="iconSpaceReserved">false</item>
</style>
<style name="CategoryPreference">
<item name="android:layout">@layout/single_pref_category</item>
<item name="allowDividerAbove">false</item>
<item name="allowDividerBelow">false</item>
<item name="iconSpaceReserved">false</item>
</style>
<style name="CheckboxPreferece">
<item name="android:layout">@layout/single_preference</item>
<item name="allowDividerAbove">false</item>
<item name="allowDividerBelow">true</item>
<item name="iconSpaceReserved">false</item>
</style>
AndroidX
如果使用 AndroidX,要显示分隔线,您只需在首选项中添加以下属性即可 XML:
<Preference
...
app:allowDividerAbove="true"
app:allowDividerBelow="true"
... />
更详细的答案在这里:
感谢Matthew Smith
的回答。
一个正确的方法是覆盖 PreferenceFragmentCompat
的 onCreateRecyclerView
方法 class
@Override
public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
RecyclerView recyclerView = super.onCreateRecyclerView(inflater, parent, savedInstanceState);
DividerItemDecoration itemDecoration = new DividerItemDecoration(getContext(), RecyclerView.VERTICAL);
recyclerView.addItemDecoration(itemDecoration);
return recyclerView;
}
这适用于 com.android.support:preference-v7:28.0.0
图书馆
在 androidx(基于
implementation 'androidx.preference:preference:1.1.1'
但不幸的是,对于具有多种首选项类型的屏幕来说,这不是一个好的解决方案(可以为 EditTextPreference 等创建子类)
public class CustomPreference extends Preference {
public CustomPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
holder.setDividerAllowedAbove(true);
}
}