Adjust margin/padding in the 'PreferenceScreen' in Android
Clash Royale CLAN TAG#URR8PPP
Adjust margin/padding in the 'PreferenceScreen' in Android
I would like to adjust the default margin/padding values for the 'PreferenceScreen' in Android, I know it's not possible to simply set it in the XML code (layout file) but Android definitely gets these values from somewhere and PROBABLY (I hope) I can set some 'style attribute(s)' and achieve it.
The values I want to adjust are:
I found this answer online:
Android: How to maximize PreferenceFragment width (or get rid of margin)?
but as per me it really uses a really bad workaround and I would like to try to manipulate some of the official parameters.
Does anyone knows how can I achieve it by adjusting the style(s) or some other fields?
implementation 'com.android.support:preference-v7:27.1.1'
– Rafael Lima
Aug 5 at 23:19
Updated my answer.
– Cheticamp
Aug 7 at 0:33
1 Answer
1
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.
preferenceTheme
<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
PreferenceThemeOverlay.v14.Material
<style name="PreferenceThemeOverlay.v14.Material">
...
<item name="preferenceStyle">@style/Preference.Material</item>
...
</style>
Preference.Material
is defined as:
Preference.Material
<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.
preference_material.xml
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:
RelativeLayout
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.
android:layout="@layout/custom_preference"
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
.
?attr/somthing
?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'
I tried option 2: copy the file from that link, and them on my
settings.xml
i edited <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:layout="@layout/preferenes_layout">
... but changing on preferences_layout
doesn't reflect on preference screen at runtime– Rafael Lima
Aug 6 at 2:40
settings.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:layout="@layout/preferenes_layout">
preferences_layout
@RafaelLima Did you change the value of the padding in
preference_layout
? If you did and don't see the change, post your settings.xml
here..– Cheticamp
Aug 6 at 11:08
preference_layout
settings.xml
sure i did... no changes on it take effect at runtime... how is this layout attribute supposed to work on
settings.xml
? i mean, i could put any non linear layout there, how would android guess where to put each component of the generated preferencescreen? is is based on the ids? anyway i didn't changed the ids or structure. i just changed the parameters for margin and padding and zero changes were applied– Rafael Lima
Aug 6 at 12:34
settings.xml
@RafaelLima It is based upon the ids, so it can't be just any old layout. My analysis was based upon the switch preference. If you are using something different, then this approach may need to change. Post your
settings.xml
so we can take a look at what you are doing. You can apply your updated layout to your switch preferences just to see how it works.– Cheticamp
Aug 6 at 12:40
settings.xml
it worked, maybe the first time i tried didn't work because i set the
android:layout="@layout/custom_preference"
only at root of settings.xml
and now with your example i've seen i need to set it for every item– Rafael Lima
Aug 8 at 2:16
android:layout="@layout/custom_preference"
settings.xml
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Are you using the preference support package?
– Cheticamp
Aug 5 at 22:44