【问题标题】:Adjust margin/padding in the 'PreferenceScreen' in Android在 Android 的“PreferenceScreen”中调整边距/填充
【发布时间】:2019-01-10 09:08:44
【问题描述】:

我想调整 Android 中“PreferenceScreen”的默认边距/填充值,我知道不可能简单地在 XML 代码(布局文件)中设置它,但 Android 肯定会从某个地方获取这些值,而且很可能(我希望)我可以设置一些“样式属性”并实现它。

我要调整的值是:

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

但就我而言,它确实使用了一个非常糟糕的解决方法,我想尝试操纵一些官方参数。

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

【问题讨论】:

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


【解决方案1】:

不幸的是,我认为您不会找到比在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>

Gradle 文件

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

【讨论】:

  • 我尝试了选项 2:从该链接复制文件,并将它们放在我的 settings.xml 我编辑 &lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:layout="@layout/preferenes_layout"&gt;... 但在 preferences_layout 上更改不会在运行时反映在首选项屏幕上
  • @RafaelLima 您是否更改了preference_layout 中的填充值?如果您看到但没有看到更改,请在此处发布您的 settings.xml..
  • 确定我做了...没有任何更改在运行时生效...这个布局属性应该如何在settings.xml 上工作?我的意思是,我可以在那里放置任何非线性布局,android如何猜测将生成的preferencescreen的每个组件放在哪里?是基于ID吗?无论如何,我没有更改 ID 或结构。我只是更改了边距和填充的参数,并且应用了零更改
  • @RafaelLima 它是基于 ids 的,所以它不能只是任何旧的布局。我的分析基于开关偏好。如果您使用不同的东西,那么这种方法可能需要改变。发布您的settings.xml,以便我们看看您在做什么。您可以将更新后的布局应用到您的开关偏好设置中,看看它是如何工作的。
  • 它成功了,也许我第一次尝试没有成功,因为我将android:layout="@layout/custom_preference"only 设置为settings.xml 的根目录,现在用你的例子我看到我需要设置它每个项目
猜你喜欢
  • 2012-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多