Android 如何管理PreferenceFragment中的分隔符?

Android 如何管理PreferenceFragment中的分隔符?,android,android-fragments,android-listview,android-preferences,Android,Android Fragments,Android Listview,Android Preferences,我开始在PreferenceFragment中处理偏好。以下是我所拥有的: 我正试图: 去掉物品之间的分隔物。我想这可以从样式中定义,但我不知道如何定义。我试着去拿那本书 首选项ListView在运行时调用 findViewById(android.R.id.list),正如我在某个地方读到的,但是 返回null 如图所示,在页眉顶部设置新的全宽分隔符。例如,在本例中,我希望在“Statistiche”的正上方有一个全宽分隔符,但不要在列表顶部的“Generali”上方 我想到的唯一方法是将分

我开始在
PreferenceFragment
中处理偏好。以下是我所拥有的:

我正试图:

  • 去掉物品之间的分隔物。我想这可以从样式中定义,但我不知道如何定义。我试着去拿那本书 首选项
    ListView
    在运行时调用
    findViewById(android.R.id.list)
    ,正如我在某个地方读到的,但是 返回null

  • 如图所示,在页眉顶部设置新的全宽分隔符。例如,在本例中,我希望在“Statistiche”的正上方有一个全宽分隔符,但不要在列表顶部的“Generali”上方

  • 我想到的唯一方法是将分隔符设置为假首选项,例如:

    <Preference
        android:layout="@layout/divider" //here I set width and a divider resource
        />
    
    <PreferenceCategory ... />
    
    
    
    这里的主要问题是我的
    PreferenceFragment
    (或者它所在的
    ActionBarActivity
    )有一些左/右填充,这使得我添加到preferences.xml中的任何分隔符都覆盖了整个宽度

    因此,我的问题是:

    • 我怎样才能去掉图像中的默认项目分隔符

    • 如何在标题上方设置全宽分隔符,或者如何消除内部片段/活动填充?当然,我的活动布局没有任何(明确的)填充


    首选项片段下添加此代码:

        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
    
            // remove dividers
            View rootView = getView();
            ListView list = (ListView) rootView.findViewById(android.R.id.list);
            list.setDivider(null);
    
        }
    

    已经完全忘记了这个问题,现在将发布答案以帮助他人。我通过在托管我的
    首选项片段的活动的
    onResume()
    方法中移动我的代码来解决问题。我认为在其他几个点上,您可以使用
    findviewbyd(android.R.id.list)
    调用非空的
    ListView

    您可能可以取消
    rootView
    检查,但同时您甚至可能想要检查
    列表!=空
    。我没有这样面对任何NPE

    因此,
    setDivider(null)
    去掉项目分隔符。我通过以下方式添加了覆盖整个屏幕宽度的分区:

    • 列表中删除填充
    • 在我的XML中添加自定义首选项:
    n


    虽然有点晚了,但我在preff屏幕中遇到了与除法器相同的问题,并找到了此解决方案: 将自定义样式设置为宿主活动并添加到样式:

       <item name="android:listDivider">@null</item>
    
    @null
    

    它实际上与通过代码设置它是一样的,但是您保存了一个findById,我认为设置槽样式看起来更清晰。对于首选项FragmentCompat,ListView不起作用。 但这很有魅力:

    <style name="PrefsTheme" parent="PreferenceThemeOverlay.v14.Material">
        <item name="android:divider">@null</item>
        <item name="android:dividerHeight">0dp</item>
    </style>
    
    
    @空的
    0dp
    
    将此添加到您的应用程序主题:

    <item name="preferenceTheme">@style/PrefsTheme</item>
    
    @style/prefsteme
    
    如果使用PreferenceFragment,则可以使用ListView。
    设置分隔符(null)

    如果您使用PreferenceFragmentCompat,则可以使用PreferenceFragmentCompat。
    setDivider(可绘制分隔符)
    setDividerHeight(int-height)

    针对新android API 24及以上版本的新解决方案(2017年12月25日

    我在stackoverflow上尝试了很多方法,但都不起作用,或者在nestest中只起作用但不起作用

    首先,您需要从当前显示片段中找到listview,并移除分隔符:

    private fun removeDividerInCurrentFragment() {
        this@YourPreferenceActivity.fragmentManager.findFragmentById(android.R.id.content)?.let {
            it.view?.findViewById<ListView?>(android.R.id.list)?.let {
                it.divider = null
                it.dividerHeight = 0
            }
        }
    }
    
    最后,通过调用fragmentManager.AddOnBackbackChangedListener(这个@YourPreferenceActivity)
    onCreate
    中注册BackbackbackChanges监听器。并通过调用fragmentManager删除Backback changes listener。在
    onDestroyed
    方法中删除Backbackback ChangedListener


    祝你好运

    您可以使用此主题重新设置分隔符的样式

    <style name="PreferenceFragment.Material">
        <item name="android:divider">@drawable/preference_list_divider_material</item>
    </style>
    
    
    @可拉伸/首选项列表分隔器材料
    
    我遇到了这个问题,我想要在偏好类别之间划分,而不是在项目本身之间划分。我发现接受的解决方案通过删除偏好项中的分隔符来满足问题1,但没有修复问题2并在偏好类别之间添加分隔符

    修正如下。 基本上覆盖PreferenceFragmentCompat的onCreateAdapter方法,并为其提供一个自定义PreferenceGroupAdapter,该方法具有一个覆盖的onBindViewHolder方法,该方法使用位置以及您需要为每个视图持有者设置的上下权限。当两个视图保持器之间都允许分隔器时,将绘制分隔器

    这是我的解决办法

    public class SettingsFragment extends PreferenceFragmentCompat {
    
        @Override
        protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
            return new CustomPreferenceGroupAdapter(preferenceScreen);
        }
    
        static class CustomPreferenceGroupAdapter extends PreferenceGroupAdapter {
    
        @SuppressLint("RestrictedApi")
        public CustomPreferenceGroupAdapter(PreferenceGroup preferenceGroup) {
            super(preferenceGroup);
        }
    
        @SuppressLint("RestrictedApi")
        @Override
        public void onBindViewHolder(PreferenceViewHolder holder, int position) {
            super.onBindViewHolder(holder, position);
            Preference currentPreference = getItem(position);
            //For a preference category we want the divider shown above.
            if(position != 0 && currentPreference instanceof PreferenceCategory) {
                holder.setDividerAllowedAbove(true);
                holder.setDividerAllowedBelow(false);
            } else {
                //For other dividers we do not want to show divider above 
                //but allow dividers below for CategoryPreference dividers.
                holder.setDividerAllowedAbove(false);
                holder.setDividerAllowedBelow(true);
            }
        }
    }
    

    AndroidX使它变得简单,但我希望它有更好的文档记录

    在XML中

    要在XML中的首选项之间添加/删除分隔符,请使用以下属性:

    <androidx.preference.PreferenceScreen
        xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <Preference
            ...
            app:allowDividerAbove="true/false"
            app:allowDividerBelow="true/false"
            ... />
    
    </androidx.preference.PreferenceScreen>
    
    (仅限AndroidX)

    让我一路走到那里。但要仅为代码中创建的特定首选项删除分隔符,我必须执行以下操作:

    val pref = object : Preference(activity) {
        override fun onBindViewHolder(holder: PreferenceViewHolder) {
            super.onBindViewHolder(holder)
            // By default, preferences created in code show dividers
            holder.setDividerAllowedAbove(false)
            holder.setDividerAllowedBelow(false)
        }
    }
    

    嗨,你得到答案了吗?。如果有的话,你能帮助解决这个问题吗?@Naruto简而言之,我使用了
    list=findviewbyd(android.R.id.list)
    ,然后是
    list.setDivider(null)
    。为了避免NPE,您需要调用此
    onResume
    ,而不是
    onCreate
    。至于另一个问题,我今天将尝试发布一个完整的答案。嘿,谢谢你的回复。我使用的是片段而不是活动。i、 e我的类看起来像
    公共类设置片段扩展首选片段
    。那么在这种情况下,我们如何才能实现?任何帮助。
    getview()
    如果我调用
    View rootView=getview(),则返回NULL类似this@Naruto请看下面我的答案。太好了!快,容易,短。我遇到的其他每一个答案(甚至都不起作用)似乎都太过分了。谢谢我们是否必须创建一个列表视图,然后将每个元素设置为相同的布局?!ANDROID 21之后,将使用RecyclerView显示基于列表的内容,因此R.id.list会删除一个RecyclerView引用,这与ListView的处理方式不同。@Fattum
    
    public class SettingsFragment extends PreferenceFragmentCompat {
    
        @Override
        protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
            return new CustomPreferenceGroupAdapter(preferenceScreen);
        }
    
        static class CustomPreferenceGroupAdapter extends PreferenceGroupAdapter {
    
        @SuppressLint("RestrictedApi")
        public CustomPreferenceGroupAdapter(PreferenceGroup preferenceGroup) {
            super(preferenceGroup);
        }
    
        @SuppressLint("RestrictedApi")
        @Override
        public void onBindViewHolder(PreferenceViewHolder holder, int position) {
            super.onBindViewHolder(holder, position);
            Preference currentPreference = getItem(position);
            //For a preference category we want the divider shown above.
            if(position != 0 && currentPreference instanceof PreferenceCategory) {
                holder.setDividerAllowedAbove(true);
                holder.setDividerAllowedBelow(false);
            } else {
                //For other dividers we do not want to show divider above 
                //but allow dividers below for CategoryPreference dividers.
                holder.setDividerAllowedAbove(false);
                holder.setDividerAllowedBelow(true);
            }
        }
    }
    
    <androidx.preference.PreferenceScreen
        xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <Preference
            ...
            app:allowDividerAbove="true/false"
            app:allowDividerBelow="true/false"
            ... />
    
    </androidx.preference.PreferenceScreen>
    
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    
        // To remove:
        setDivider(null);
    
        // To change:
        setDivider(ContextCompat.getDrawable(getActivity(), R.drawable.your_drawable));
        setDividerHeight(your_height);
    }
    
    val pref = object : Preference(activity) {
        override fun onBindViewHolder(holder: PreferenceViewHolder) {
            super.onBindViewHolder(holder)
            // By default, preferences created in code show dividers
            holder.setDividerAllowedAbove(false)
            holder.setDividerAllowedBelow(false)
        }
    }