首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Android:如何在首选项屏幕中删除边距/填充

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

Stack Overflow用户
提问于 2013-08-29 19:11:23
回答 17查看 32.2K关注 0票数 88

我在设计首选项屏幕时遇到了非常奇怪的问题。虽然我没有在布局上给出任何空白,但它在左边留下了一些空间。

如下图所示:

XML:

代码语言:javascript
复制
   <PreferenceScreen android:title="demo" >
       <CheckBoxPreference
           android:defaultValue="false"
            android:key="prefSync"`
            android:title="Auto Sync" />
    </PreferenceScreen>

在屏幕中添加复选框首选项是不是做错了什么?

EN

回答 17

Stack Overflow用户

发布于 2018-11-21 05:52:50

更新androidx的这个。

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

代码语言:javascript
复制
app:iconSpaceReserved="false"

当然,您还需要将此代码添加到PreferenceScreen声明本身的xml顶部:

代码语言:javascript
复制
xmlns:app="http://schemas.android.com/apk/res-auto"

针对自定义首选项的跟进

我注意到,在自定义首选项的情况下,特别是在旧设备上,这种解决方案并不总是有效的。例如,像这样的首选项仍然可以缩进:

代码语言:javascript
复制
com.example.preference.SomeCustomPreference
    android:id="@+id/some_custom_preference"
    android:name="Custom Preference"
    android:key="@string/custom_pref_key"
    android:summary="@string/custom_pref_summary"
    android:title="@string/preference_custom_title"
    app:iconSpaceReserved="false"

该问题可追溯到自定义preference类中第三个构造函数参数的使用。如果传递第三个参数,则列表项将缩进。如果省略它,列表将正确对齐:

代码语言:javascript
复制
class SomeCustomPreference
@JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = android.R.attr.someCustomPreferenceStyle
) : DialogPreference(context, attrs, defStyle) {

    override fun getDialogLayoutResource(): Int {
        return R.layout.my_layout
    }
}

而不是这样,使用以下命令:

代码语言:javascript
复制
class SomeCustomPreference
@JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null
) : DialogPreference(context, attrs) {

    override fun getDialogLayoutResource(): Int {
        return R.layout.my_layout
    }
}

这归功于这个非常老的post中的@CommonsWare。

票数 165
EN

Stack Overflow用户

发布于 2018-07-28 14:40:31

我已经报告了这个问题 (你也可以在那里查看我的变通项目),但现在,我已经找到了一些老生常谈的,但很容易克服这个问题的方法:

对于

  • PreferenceCategory,我将其布局的起始/左填充设置为0。
  • 对于其他类型的首选项,我选择隐藏icon_frame,以防它们没有图标。

这是代码。只需从这个类扩展,其余的就会自动完成:

Kotlin

代码语言:javascript
复制
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)
        }
    }
}

Java

代码语言:javascript
复制
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());
        }
    }
}

以及结果(可以在的中找到XML示例,我已经创建了来检查它):

这段代码有点危险,所以请确保每次更新库时,都要检查它是否工作正常。

此外,在某些特殊情况下,它可能不能很好地工作,例如,当您为首选项定义自己的android:layout时,因此您必须为此修改它。

得到了一个更好、更正式的解决方案:

对于每个首选项,请使用app:iconSpaceReserved="false"。这应该可以很好地工作,但由于某些原因,它有一个(已知的)错误,它不能在PreferenceCategory上工作。据报道是,应该在不久的将来修复。

所以现在你可以使用我写的变通方法和这个标志的混合版本。

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

Kotlin

代码语言:javascript
复制
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
        }
    }

Java

代码语言:javascript
复制
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);
        }
    }
}

编辑:在谷歌最终修改库(链接)后,你可以为每个首选项设置标志,或者使用这个解决方案为你做所有的事情:

代码语言:javascript
复制
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)
                }
            }
}

只要从它扩展,你就不会有无用的填充你的喜好。示例项目,在那里我也要求有一个官方的方法来避免它,而不是那些技巧。请考虑出演它。

票数 54
EN

Stack Overflow用户

发布于 2018-12-29 19:15:14

来自here的简单的工作解决方案。

无需写入所有首选项,即可在所有首选项app:iconSpaceReserved="false"中运行

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

代码语言:javascript
复制
<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>

<bool>修复所有Preference的默认值iconSpacePreserved<dimen>修复PreferenceCategory。

编辑:如果你使用的是androidx.preference:preference:1.1.1,你就不需要dimen preference_category_padding_start了。在Android 6-10上进行了测试。

票数 36
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18509369

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档