在Android的“ PreferenceScreen”中调整边距/填充

时间:2018-08-02 14:36:09

标签: android android-preferences android-styles android-settings preferencescreen

我想为Android中的“ PreferenceScreen”调整默认的边距/边距值,我知道无法简单地在XML代码(布局文件)中进行设置,但是Android绝对可以从某个地方获取这些值,并且PROBABLY(我希望)我可以设置一些“样式属性”并实现它。

我要调整的值是:

enter image description here

我在网上找到了这个答案: Android: How to maximize PreferenceFragment width (or get rid of margin)?

但是根据我个人的观点,它确实使用了非常糟糕的解决方法,我想尝试操纵一些官方参数。

有人知道如何通过调整样式或其他字段来实现它吗?

1 个答案:

答案 0 :(得分:2)

不幸的是,我认为您找不到比Android: How to maximize PreferenceFragment width (or get rid of margin)?中发现的更好的答案。我将解释原因,并为您提供一种替代方法,您认为它可能比参考答案中给出的方法差。

首选项屏幕下方是我们将要识别的每个项目的布局。这些是我们将使用的首选项库依赖项:

implementation 'com.android.support:preference-v7:27.1.1'
implementation 'com.android.support:preference-v14:27.1.1'

主题的preferenceTheme属性定义首选项的外观。

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    ...
    <!-- Theme for the preferences -->
    <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>

PreferenceThemeOverlay.v14.Material上看到父链(ctrl-B)

<style name="PreferenceThemeOverlay.v14.Material">
...
<item name="preferenceStyle">@style/Preference.Material</item>
...
</style>    

Preference.Material定义为:

<style name="Preference.Material">
    <item name="android:layout">@layout/preference_material</item>
</style>    

首选项的布局为preference_material.xml。这是source

此布局的以下部分使我们感兴趣:

...
<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>
...

如您所见,RelativeLayout的顶部和底部填充是硬编码的。由于未使用样式属性,因此无法覆盖填充。由于采用这种硬编码,因此您有两种选择:

  1. 使用您发现的答案中概述的“非常糟糕的解决方法” ,其中涉及Java代码来修改填充,或者

  2. 通过在XML中为您的首选项定义android:layout="@layout/custom_preference"来使用自己的布局。您可以复制Android布局并进行修改。

每种方法都有缺点,因此请选择您认为最能解决的方法。


以下是一个小型应用程序的关键组件,演示了首选项布局的替换。

MainActivity.java
为了方便起见,该活动会在首选项片段中滚动。

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
简单地定义首选项片段的位置。

<?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
进行了一些修改,以适应此文件的使用,主要是将?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>

成绩文件

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'
}