【问题标题】:PreferenceFragmentCompat has padding on PreferenceCategory that I can't get rid ofPreferenceFragmentCompat 在 PreferenceCategory 上有我无法摆脱的填充
【发布时间】:2019-01-02 06:21:14
【问题描述】:

所以我一直在尝试使用 androidx.preference.PreferenceFragmentCompat 创建一个设置活动,并且一切正常。

但是由于某种原因,偏好类别和偏好本身都存在一些填充。我设法通过使用 app:iconSpaceReserved="false" 摆脱了首选项上的填充,但这似乎不适用于类别。

Image

我已经尝试了所有不同的主题,PreferenceThemeOverlay.v14.Material 等,但它们似乎没有什么不同

这是我的所有代码!

SettingsActivity.java

import android.os.Bundle;

import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

public class SettingsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_settings);

        Toolbar toolbar = findViewById(R.id.settings_toolbar);
        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setDisplayShowTitleEnabled(false);
        }

    }
}

activity_settings.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SettingsActivity">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/settings_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            style="@style/ToolbarTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/title_settings"
            android:textColor="@color/font_dark_primary" />

    </androidx.appcompat.widget.Toolbar>

    <fragment
        android:name="com.henrytwist8gmail.fullcart.SettingsTestFragment"
        android:tag="settings_fragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/settings_toolbar" />

</androidx.constraintlayout.widget.ConstraintLayout>

SettingsTestFragment.java

import android.os.Bundle;

import androidx.preference.PreferenceFragmentCompat;

public class SettingsTestFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {

        setPreferencesFromResource(R.xml.preferences_test, rootKey);
    }
}

preferences_test.xml

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory android:title="test" >

        <Preference android:title="testPref" />
    </PreferenceCategory>

</PreferenceScreen>

我的依赖是...

implementation 'com.google.android.material:material:1.0.0-beta01'
implementation 'androidx.preference:preference:1.0.0-beta01'
implementation 'androidx.constraintlayout:constraintlayout:1.1.2'

【问题讨论】:

标签: android android-appcompat android-preferences preferencefragment androidx


【解决方案1】:

实际上有一个更好的 hack 可以解决这个问题,也可以使用资源覆盖:

创建res/values-sw360dp-v13/values-preference.xml:

<?xml version="1.0" encoding="utf-8"?>

<resources xmlns:tools="http://schemas.android.com/tools">
    <bool name="config_materialPreferenceIconSpaceReserved" tools:ignore="MissingDefaultResource,PrivateResource">false</bool>
    <dimen name="preference_category_padding_start" tools:ignore="MissingDefaultResource,PrivateResource">0dp</dimen>
</resources>

&lt;bool&gt; 修复了所有Preference 的默认值iconSpacePreserved&lt;dimen&gt; 修复了 PreferenceCategory

编辑:如果您使用androidx.preference:preference:1.1.0-alpha01 或更高版本,则不需要preference_category_padding_start 修复,只需config_materialPreferenceIconSpaceReserved 就足够了。

【讨论】:

  • 一次性修复所有首选项的最佳解决方案
  • 整屏已修复。完美!
  • 这太棒了,它确实修复了每个首选项屏幕!遗憾的是,即使 Google 确实修复了 AndroidX 的问题,也没有针对支持库的官方修复。
  • @Bouh 因为原来的值在androidx.preference中设置为values-sw360dp-v13下的true,所以我们将其重置回同一目录下的false
  • @James Poulose 只需创建具有上述内容的文件就足够了,它会被Android资源编译器读取并自动覆盖配置。
【解决方案2】:

我通过样式解决方法解决了问题。它适用于 PreferenceCategory

请使用:app:iconSpaceReserved="false"。

[styles.xml]

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="preferenceTheme">@style/AppPreferenceTheme</item>
</style>

<style name="AppPreferenceTheme" parent="@style/PreferenceThemeOverlay.v14.Material">
    <item name="preferenceCategoryStyle">@style/FixForPreferenceCategoryStyle</item>

    <!-- <item name="android:textColor">#ffffffff</item> -->
    <!-- <item name="android:textColorSecondary">#b3ffffff</item> -->
    <!--when the check box is checked-->
    <!--<item name="colorControlNormal">#FF4081</item>-->
    <!--when the check box is unchecked -->
    <!--<item name="colorControlActivated">#81FF40</item>-->
</style>

<style name="FixForPreferenceCategoryStyle" parent="@style/Preference.Category.Material">
    <item name="android:layout">@layout/_preference_category_material</item>
</style>

<color name="_preference_fallback_accent_color">@color/colorAccent</color>

[_preference_category_material.xml] 复制自“@layout/preference_category_material”。

@dimen/preference_category_padding_start 替换为 android:paddingLeft="0dp"。添加自定义颜色@color/_preference_fallback_accent_color

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="8dp"
    android:layout_marginTop="8dp"
    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="0dp"><!-- SET to 0dp -->
        <!--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"/>
        <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>

【讨论】:

  • 如果使用androidx,只需将android.support.v7.internal.widget.PreferenceImageView 替换为ImageView 即可编译代码
  • 如果您在 XML 中使用 android:iconSpaceReserved="false",这将不起作用。但是如果你使用 setIconSpaceReserved (false) 就可以了
【解决方案3】:

如果使用 AndroidX,您可以通过简单地将以下属性添加到 XML 中的 Preferences 和 Preference Categories 中来添加/删除额外的填充:

<androidx.preference.PreferenceScreen
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <Preference
        ...
        app:iconSpaceReserved="true/false"
        .../>

</androidx.preference.PreferenceScreen>

true 添加额外的填充,false 删除它。

【讨论】:

    【解决方案4】:

    该修复程序目前以 alpha 版本发布。你可以使用

    implementation 'androidx.preference:preference:1.1.0-alpha01'

    或你的 build.gradle 中最新发布的一个

    【讨论】:

      【解决方案5】:

      此错误已在最新版本的 androidx 偏好设置中修复

      尝试在你的Build.Gradle中遵循依赖关系

          implementation 'androidx.preference:preference:1.1.0'
      

      【讨论】:

        【解决方案6】:

        我发现以编程方式完成它更容易:

        private fun Preference.removeIconSpace() {
            setIconSpaceReserved(false)
            if (this is PreferenceGroup) {
                for (i in 0 until preferenceCount) {
                    getPreference(i).removeIconSpace()
                }
            }
        }
        
        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
            setPreferencesFromResource(R.xml.settings, rootKey)
            …
            preferenceScreen.removeIconSpace()
        }
        

        【讨论】: