Android:如何删除首选项屏幕中的边距/填充

Dor*_*ory 55 android preference checkboxpreference

我在设计偏好屏幕时遇到了非常奇怪的问题.虽然我没有给出任何布局余量,但是左边留有一些空间.

如下图所示: 在此输入图像描述

XML:

   <PreferenceScreen android:title="demo" >
       <CheckBoxPreference
           android:defaultValue="false"
            android:key="prefSync"`
            android:title="Auto Sync" />
    </PreferenceScreen>
Run Code Online (Sandbox Code Playgroud)

我在屏幕上添加复选框首选项时做错了什么?

And*_*Dev 85

为androidx更新此内容.

经过大量的实验,我通过将此问题添加具有多余缩进的每个首选项来解决此问题:

app:iconSpaceReserved="false"
Run Code Online (Sandbox Code Playgroud)

当然,您还需要将它添加到xml顶部的PreferenceScreen声明中:

xmlns:app="http://schemas.android.com/apk/res-auto"
Run Code Online (Sandbox Code Playgroud)

  • 那喜好类别呢?首选项类别似乎无效 (5认同)
  • 我不知道你是谁,但我会找到你的,谢谢你!:) (2认同)

and*_*per 47

我在这里报告了这个问题(你也可以在那里查看我的解决方案项目),但是现在,我发现了一些hack-y,但却很容易克服这个问题:

  • 因为PreferenceCategory,我将其布局的开始/左边填充设置为0.

  • 对于其他类型的偏好,我选择隐藏它icon_frame以防万一没有图标.

这是代码.只需从这个类扩展,其余的是自动的:

科特林

abstract class BasePreferenceFragment : PreferenceFragmentCompat() {

    override fun onCreateAdapter(preferenceScreen: PreferenceScreen?): RecyclerView.Adapter<*> {
        return object : PreferenceGroupAdapter(preferenceScreen) {
            override fun onBindViewHolder(holder: PreferenceViewHolder, position: Int) {
                super.onBindViewHolder(holder, position)
                val preference = getItem(position)
                if (preference is PreferenceCategory)
                    setZeroPaddingToLayoutChildren(holder.itemView)
                else
                    holder.itemView.findViewById<View?>(R.id.icon_frame)?.visibility = if (preference.icon == null) View.GONE else View.VISIBLE
            }
        }
    }

    private fun setZeroPaddingToLayoutChildren(view: View) {
        if (view !is ViewGroup)
            return
        val childCount = view.childCount
        for (i in 0 until childCount) {
            setZeroPaddingToLayoutChildren(view.getChildAt(i))
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
                view.setPaddingRelative(0, view.paddingTop, view.paddingEnd, view.paddingBottom)
            else
                view.setPadding(0, view.paddingTop, view.paddingRight, view.paddingBottom)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Java的

public abstract class BasePreferenceFragmentCompat extends PreferenceFragmentCompat {
    @Override
    protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
        return new PreferenceGroupAdapter(preferenceScreen) {
            @SuppressLint("RestrictedApi")
            @Override
            public void onBindViewHolder(PreferenceViewHolder holder, int position) {
                super.onBindViewHolder(holder, position);
                Preference preference = getItem(position);
                if (preference instanceof PreferenceCategory)
                    setZeroPaddingToLayoutChildren(holder.itemView);
                else {
                    View iconFrame = holder.itemView.findViewById(R.id.icon_frame);
                    if (iconFrame != null) {
                        iconFrame.setVisibility(preference.getIcon() == null ? View.GONE : View.VISIBLE);
                    }
                }
            }
        };
    }

    private void setZeroPaddingToLayoutChildren(View view) {
        if (!(view instanceof ViewGroup))
            return;
        ViewGroup viewGroup = (ViewGroup) view;
        int childCount = viewGroup.getChildCount();
        for (int i = 0; i < childCount; i++) {
            setZeroPaddingToLayoutChildren(viewGroup.getChildAt(i));
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
                viewGroup.setPaddingRelative(0, viewGroup.getPaddingTop(), viewGroup.getPaddingEnd(), viewGroup.getPaddingBottom());
            else
                viewGroup.setPadding(0, viewGroup.getPaddingTop(), viewGroup.getPaddingRight(), viewGroup.getPaddingBottom());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

而结果(XML样本可以发现这里这个谷歌的样品,我已经创建这里来看看):

在此输入图像描述

此代码有点危险,因此请确保每次更新库时,检查它是否正常工作.

此外,它可能不适用于某些特殊情况,例如当您为首android:layout选项定义自己的情况时,因此您必须为此修改它.


有一个更好的,更官方的解决方案:

对于每个偏好,请使用app:iconSpaceReserved="false".这应该可以正常工作,但由于某种原因,有一个(已知的)错误,它不适用于PreferenceCategory.据报道,在这里,并应固定在不久的将来.

所以现在你可以使用我写的解决方法和这个标志的混合版本.


编辑:找到另一种解决方案.这个将覆盖所有的首选项,并isIconSpaceReserved为每个首选项设置.遗憾的是,正如我上面所写,如果你使用PreferenceCategory,它会破坏它,但如果你不使用它应该可以正常工作:

科特林

abstract class BasePreferenceFragment : PreferenceFragmentCompat() {

    override fun setPreferenceScreen(preferenceScreen: PreferenceScreen?) {
        super.setPreferenceScreen(preferenceScreen)
        if (preferenceScreen != null) {
            val count = preferenceScreen.preferenceCount
            for (i in 0 until count)
                preferenceScreen.getPreference(i)!!.isIconSpaceReserved = false
        }
    }
Run Code Online (Sandbox Code Playgroud)

Java的

public class BasePreferenceFragment extends PreferenceFragmentCompat {

    @Override
    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
        super.setPreferenceScreen(preferenceScreen);
        if (preferenceScreen != null) {
            int count = preferenceScreen.getPreferenceCount();
            for (int i = 0; i < count; i++)
                preferenceScreen.getPreference(i).setIconSpaceReserved(false);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:在Google最终修复了库(此处链接)之后,您可以为每个首选项设置标记,或者使用此解决方案为您执行此操作:

abstract class BasePreferenceFragment : PreferenceFragmentCompat() {
    private fun setAllPreferencesToAvoidHavingExtraSpace(preference: Preference) {
        preference.isIconSpaceReserved = false
        if (preference is PreferenceGroup)
            for (i in 0 until preference.preferenceCount)
                setAllPreferencesToAvoidHavingExtraSpace(preference.getPreference(i))
    }

    override fun setPreferenceScreen(preferenceScreen: PreferenceScreen?) {
        if (preferenceScreen != null)
            setAllPreferencesToAvoidHavingExtraSpace(preferenceScreen)
        super.setPreferenceScreen(preferenceScreen)

    }

    override fun onCreateAdapter(preferenceScreen: PreferenceScreen?): RecyclerView.Adapter<*> =
            object : PreferenceGroupAdapter(preferenceScreen) {
                @SuppressLint("RestrictedApi")
                override fun onPreferenceHierarchyChange(preference: Preference?) {
                    if (preference != null)
                        setAllPreferencesToAvoidHavingExtraSpace(preference)
                    super.onPreferenceHierarchyChange(preference)
                }
            }
}
Run Code Online (Sandbox Code Playgroud)

只需从它扩展,您将无法根据自己的喜好使用无用的填充.这里的示例项目,我也要求有一个正式的方法来避免它,而不是那些技巧.请考虑主演它.

  • 我什至不明白为什么这是一回事。如果没有替代品或损坏的替代品,那么Google弃用/删除/阻止API会发生什么? (2认同)

t0m*_*t0m 20

这里简单的工作解决方案:

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

<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>
Run Code Online (Sandbox Code Playgroud)

<bool>修正的默认值iconSpacePreserved所有Preference; 该<dimen>修正的PreferenceCategory.


San*_*hah 7

试试这个:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View v = super.onCreateView(inflater, container, savedInstanceState);
    if(v != null) {
        ListView lv = (ListView) v.findViewById(android.R.id.list);
        lv.setPadding(10, 10, 10, 10);
    }
    return v;
}
Run Code Online (Sandbox Code Playgroud)

您可以使用以下方法设置填充: setPadding();

  • 嘿@David,感谢您的回复。但我没有为首选项屏幕创建任何自定义视图。我正在使用默认的。 (2认同)

小智 5

不幸的是,上面的内容对我没有任何作用。

简短回答

我通过在自定义首选项布局的最上面的容器上使用负边距解决了这个问题。

脚步:

  • 为首选项创建自定义布局(例如preference_category.xml)
  • 通过将 android:layout 参数添加到 XML 中的首选项标记来指定您的首选项使用自定义布局
  • 应用负边距

详细解答:

首选项 XML:

    <android.support.v7.preference.PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:title="@string/settings_title" >

    <android.support.v7.preference.PreferenceCategory
        android:layout="@layout/preference_category"
        android:key="settings_list"
        android:title="@string/pref_category_settings" />
    <android.support.v7.preference.SwitchPreferenceCompat
        android:layout="@layout/preference_row"
        android:icon="@drawable/ic_nav_switch"
        android:key="pref_switch"
        android:title="@string/pref_switch_title" />

    </android.support.v7.preference.PreferenceScreen>
Run Code Online (Sandbox Code Playgroud)

首选项行的自定义布局,删除不必要的左右边距:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="-12dp"
    android:layout_marginEnd="-8dp"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:gravity="center_vertical">

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@android:id/icon"
            android:layout_width="58dp"
            android:layout_height="58dp"
            android:padding="8dp"
            android:layout_gravity="center"
            android:visibility="visible" />

    </RelativeLayout>

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="15dp"
        android:layout_marginEnd="6dp"
        android:layout_marginTop="6dp"
        android:layout_marginBottom="6dp"
        android:layout_weight="1">

        <TextView
            android:id="@android:id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:singleLine="true"
            android:textAppearance="?android:attr/textAppearanceListItem"
            android:ellipsize="marquee"
            android:fadingEdge="horizontal" />

        <TextView
            android:id="@android:id/summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@android:id/title"
            android:layout_alignStart="@android:id/title"
            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
            android:textColor="?android:attr/textColorSecondary"
            android:maxLines="2"/>

    </RelativeLayout>

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

    </LinearLayout>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

首选项类别的自定义布局,删除不必要的左右边距:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColor="@color/colorAccent"
    android:textStyle="bold"
    android:textSize="12sp"
    android:gravity="center_vertical"
    android:textAllCaps="true"
    android:layout_marginStart="-4dp"
    android:layout_marginEnd="-8dp"
    android:id="@+android:id/title" />
Run Code Online (Sandbox Code Playgroud)


mtr*_*tha 5

如果您使用的是com.android.support:preference-v7库,请确保托管您的首选项的活动的主题已preferenceTheme设置为v14材质首选项主题叠加层:

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


MDX*_*ave -5

添加android:defaultValue="false"到您的<PreferenceScreen [...]标签:

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