In my settings I have multiple preferences that don't have lines in between them, creating an ugly look. How do I fix this?

- 671
- 2
- 11
- 30
-
this link may be use full to you check it http://www.javatpoint.com/android-preferences-example – sunita Mar 18 '17 at 03:59
-
This is the correct look for Material Design. I agree that it looks odd, but your app will look out of place if you don't follow it. – Tenfour04 Jul 09 '17 at 22:52
-
@Tenfour04 could you link where it specifically says that? – Pike D. Jul 09 '17 at 22:53
-
@PikeD. Well, I looked it up and realized I'm wrong. The spec doesn't mention it. I was making an assumption because it is the default styling in Marshmallow+ and AppCompat. But why expend effort trying to look different than Google's own apps, when the result is that your UI is not cohesive with the rest of the system? – Tenfour04 Jul 09 '17 at 22:57
6 Answers
AndroidX
If using AndroidX, to show dividers you can simply add the following attributes in your Preference XML:
<Preference
...
app:allowDividerAbove="true"
app:allowDividerBelow="true"
... />
A more detailed answer here: https://stackoverflow.com/a/55981453/2836371

- 3,991
- 31
- 25
The following is for AndroidX:
In AndroidX, getListView() returns a RecyclerView.
Dividing lines can be added to RecyclerViews using .addItemDecoration()
This should be done after the RecyclerView has been inflated in onActivityCreated().
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
RecyclerView recyclerView = getListView();
DividerItemDecoration itemDecoration = new DividerItemDecoration(context, RecyclerView.VERTICAL);
recyclerView.addItemDecoration(itemDecoration);
}

- 79
- 2
- 4
The most appropriate solution I found is to set up layouts for categories and preferences in XML. For example
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>
Maybe additionally it will be required to modify styles and use this style instead of default:
<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>

- 4,464
- 2
- 24
- 33
-
1I have been looking for app:iconSpaceReserved="false" for waaaaaayyyyy too long. I've learned more from the code snippets in your post than I have in 100 articles and the official docs about preference items. Thanks! <3 – jungledev Jun 27 '19 at 22:44
-
the problem comes that the app:iconSpaceReserved is for API 26 and above :( – Pulkit Mar 12 '21 at 19:11
A good way to create dividers in the whole settings screen in androidx (based on this post) is to create a Subclass of Preference and override onBindViewHolder then use it in xml. It works in
implementation 'androidx.preference:preference:1.1.1'
but unfortunately it is not a good solution for Screens with more than one Preference type (one may create subclass for EditTextPreference etc.)
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);
}
}

- 499
- 1
- 5
- 9
I think you're trying to add the dividers in custom preference.xml.
It should be ease If you're using both PreferenceActivity or Preference Fragment.
Just go to the onCreate method and call this
ListView list = getListView();
list.setDivider(); // pass null for no dividers or a valid drawable for dividers.

- 1,452
- 1
- 12
- 20
Thanks to Matthew Smith
's answer.
A proper way is to overwrite thePreferenceFragmentCompat
's onCreateRecyclerView
method of 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;
}
This works for com.android.support:preference-v7:28.0.0
library

- 1,116
- 6
- 16

- 449
- 4
- 11