如何在偏好设置(设置菜单)中添加分隔线?

5
在我的设置中,有多个偏好设置之间没有分隔线,看起来不美观。我该如何解决?Image of my settings menu

这个链接可能对你有用,查看它:http://www.javatpoint.com/android-preferences-example - sunita
这是Material Design的正确外观。我同意它看起来很奇怪,但如果你不遵循它,你的应用程序将显得格格不入。 - Tenfour04
@Tenfour04,你能链接到具体说明吗? - Pike D.
@PikeD。好的,我查了一下发现我错了。规范中没有提到这一点。我之前是做出了一个假设,因为它是Marshmallow+和AppCompat的默认样式。但是,为什么要费力地尝试与谷歌自己的应用程序不同呢?结果是你的用户界面与系统的其他部分不协调。 - Tenfour04
6个回答

14

AndroidX

如果使用 AndroidX,您可以在偏好设置的 XML 文件中添加以下属性来显示分隔线:

<Preference
    ...
    app:allowDividerAbove="true"
    app:allowDividerBelow="true"
    ... />

更详细的答案在这里:https://dev59.com/5V4c5IYBdhLWcg3wl7Mg#55981453


7
以下内容是关于AndroidX的:
在AndroidX中,getListView()返回一个RecyclerView。
可以使用.addItemDecoration()将分割线添加到RecyclerView中。
这应该在onActivityCreated()中RecyclerView被填充后执行。
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    RecyclerView recyclerView = getListView();
    DividerItemDecoration itemDecoration = new DividerItemDecoration(context, RecyclerView.VERTICAL);
    recyclerView.addItemDecoration(itemDecoration);
}

3
我找到的最合适的解决方案是使用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>

1
我已经寻找app:iconSpaceReserved="false"太久了。我从您的帖子中的代码片段中学到的比我在100篇关于首选项项目的文章和官方文档中学到的还要多。谢谢!<3 - jungledev
问题在于app:iconSpaceReserved是适用于API 26及以上版本的 :( - Pulkit

2
在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);
  }

}


1
感谢Matthew Smith的回答。
一种正确的方法是重写PreferenceFragmentCompat类的onCreateRecyclerView方法。
    @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库。

1
我认为您正在尝试在自定义preference.xml中添加分隔符。
如果您同时使用PreferenceActivity或Preference Fragment,则应该很容易。
只需转到onCreate方法并调用此方法即可。
ListView list = getListView();
list.setDivider(); // pass null for no dividers or a valid drawable for dividers.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接