PreferenceFragmentCompat has padding on PreferenceCategory that I can't get rid of
This Bug has been Fixed in Latest Release of androidx preference
Try Following Dependency in yout Build.Gradle
implementation 'androidx.preference:preference:1.1.0'
PreferenceFragmentCompat adds margin to preference items
If you are using AndroidX, you can use Preference.setIconSpaceReserved(boolean iconSpaceReserved)
method.
So, you will have:
item_Confirmation.setIconSpaceReserved(false);
You can also check this answer.
PreferenceFragmentCompat has iconSpaceReserved true by default
I've posted this on the Issue Tracker and got the following answer:
This is intended and part of the Material spec for Settings. See
Material Design guide under 'Alignment'.
Preference library version 28 creates huge padding on the left side of each preference
Try set:
app:iconSpaceReserved="false"
Adjust margin/padding in the 'PreferenceScreen' in Android
Unfortunately, I don't think that you are going to find a better answer than you have already discovered in Android: How to maximize PreferenceFragment width (or get rid of margin)?. I will explain why and give you an alternative which you may consider to be worse than the one presented in the answer you reference.
Underneath the preference screen is a layout for each item which we will identify. These are the preference library dependencies that we will use:
implementation 'com.android.support:preference-v7:27.1.1'
implementation 'com.android.support:preference-v14:27.1.1'
The preferenceTheme
attribute of the theme defines how the preferences will look.
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
...
<!-- Theme for the preferences -->
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>
Going up the parent chain (ctrl-B) from PreferenceThemeOverlay.v14.Material
we see
<style name="PreferenceThemeOverlay.v14.Material">
...
<item name="preferenceStyle">@style/Preference.Material</item>
...
</style>
Preference.Material
is defined as:
<style name="Preference.Material">
<item name="android:layout">@layout/preference_material</item>
</style>
The layout for the preference is preference_material.xml
. Here is the source.
The following section of this layout interests us:
...
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<TextView android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?attr/textAppearanceListItem"
android:ellipsize="marquee" />
<TextView android:id="@+id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:layout_alignStart="@id/title"
android:textAppearance="?attr/textAppearanceListItemSecondary"
android:textColor="?attr/textColorSecondary"
android:maxLines="10"
android:ellipsize="end" />
</RelativeLayout>
...
As you can see, the top and bottom padding for the RelativeLayout
is hard-coded. Since a style attribute is not used, there is no way to override the padding. Because of this hard-coding, you have two choices:
Use the "really bad workaround" outlined in the answer you found which involves Java code to modify the padding, or,
Use your own layout by defining
android:layout="@layout/custom_preference"
in the XML for your preferences. You can copy the Android layout and make your modifications.
Each method has drawbacks, so pick the one you think you can best deal with.
The following are key components of a small app that demonstrates substitution of the preference layout.
MainActivity.java
This activity rolls in the preference fragment for convenience.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
Fragment preferenceFragment = new PrefsFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.prefContainer, preferenceFragment);
ft.commit();
}
}
public static class PrefsFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle bundle, String s) {
addPreferencesFromResource(R.xml.app_preferences);
}
}
}
app_preference.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v7.preference.Preference
android:key="preference"
android:layout="@layout/custom_pref_layout"
android:summary="Doesn't really do anything."
android:title="Preference Title" />
<android.support.v7.preference.EditTextPreference
android:defaultValue="Default EditTextPreference value"
android:dialogMessage="EditTextPreference Dialog Message"
android:inputType="number"
android:key="editTextPreference"
android:layout="@layout/custom_pref_layout"
android:summary="EditTextPreference Summary"
android:title="EditTextPreference Title" />
<android.support.v7.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="switchPreference"
android:layout="@layout/custom_pref_layout"
android:summary="SwitchPreference Summary"
android:title="SwitchPreference Title" />
<android.support.v7.preference.CheckBoxPreference
android:defaultValue="true"
android:key="checkBoxPreference"
android:layout="@layout/custom_pref_layout"
android:summary="CheckBoxPreference Summary"
android:title="CheckBoxPreference Title" />
<android.support.v7.preference.ListPreference
android:defaultValue="180"
android:entries="@array/pref_sync_frequency_titles"
android:entryValues="@array/pref_sync_frequency_values"
android:key="list_preference"
android:layout="@layout/custom_pref_layout"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="List Preference Title" />
</android.support.v7.preference.PreferenceScreen>
activity_main.xml
Simply defines a home for the preference fragment.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/prefContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.preferencecustomlayout.MainActivity" />
custom_pref_layout.xml
Some modification have been made to accommodate usage of this file mainly updated ?attr/somthing
to ?android:attr/something
.
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 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.
-->
<!-- Layout for a Preference in a PreferenceActivity. The
Preference is able to place a specific widget for its particular
type in the "widget_frame" layout. -->
<!-- Modified from the original to accommodate usage as a local layout file. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator"
android:clipToPadding="false"
android:gravity="center_vertical"
android:minHeight="?attr/listPreferredItemHeightSmall"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingStart="?android:attr/listPreferredItemPaddingStart">
<LinearLayout
android:id="@+id/icon_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="-4dp"
android:gravity="start|center_vertical"
android:minWidth="60dp"
android:orientation="horizontal"
android:paddingBottom="4dp"
android:paddingEnd="12dp"
android:paddingTop="4dp">
<com.android.internal.widget.PreferenceImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxHeight="48dp"
android:maxWidth="48dp" />
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingBottom="16dp"
android:paddingTop="16dp">
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:singleLine="true"
android:textAppearance="?attr/textAppearanceListItem" />
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@android:id/title"
android:layout_below="@android:id/title"
android:ellipsize="end"
android:maxLines="10"
android:textAppearance="?attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary" />
</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:orientation="vertical"
android:paddingStart="16dp" />
</LinearLayout>
Gradle file
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion '27.0.3'
defaultConfig {
applicationId "com.example.preferencecustomlayout"
minSdkVersion 18
targetSdkVersion 27
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:preference-v7:27.1.1'
implementation 'com.android.support:preference-v14:27.1.1'
}
How to style PreferenceFragmentCompat
Following this.
Change
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
to
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
Then, change in build.gradle
dependencies
com.android.support:preference-v7
to
com.android.support:preference-v14
Related Topics
Displaying Yuv Image in Android
Live Audio Recording and Playing in Android and Thread & Callback Handling
Error:(9, 5) Error: Resource Android:Attr/Dialogcornerradius Not Found
Failure [Install_Failed_Invalid_Apk]
Dialogfragment with Clear Background (Not Dimmed)
Android:Static Variable Null on Low Memory
How Does Bitmap Allocation Work on Oreo, and How to Investigate Their Memory
Offline Mode for Android App Using the Google Maps API
Where Does Android View.Scrollto(X, Y) Scroll To
Android Taking Screenshot of Offscreen Page
Why Ondraw Is Not Called After Invalidate()
The Application Icon Does Not Show on Action Bar
Android Google+ Integration - Repeated Userrecoverableauthexception
Android - Hide All Shown Toast Messages
Voice Recognition Stops Listening After a Few Seconds
How to Keep Android Applications Always Be Logged in State
Mediaplayer Error (1, -1004) Aka Media_Error_Io Trying to Stream Music on Samsung S3