如何管理PreferenceFragment中的分隔符?

时间:2015-01-03 01:40:58

标签: android android-fragments android-listview android-preferences

我开始处理PreferenceFragment中的偏好设置。这就是我所拥有的:

my_preferences

我试图:

  1. 摆脱物品之间的分隔物。我想这可以从样式中定义,但我无法弄清楚如何。我试过了 在运行时调用时优先级ListView findViewById(android.R.id.list),正如我在某处读到的那样,但它 返回null。

  2. 在标题顶部设置新的全宽分隔符,如here所示。例如,在这种情况下,我希望在#34; Statistiche"之上有一个全宽度分频器,但不要超过" Generali"这是最重要的。

  3. 我想到的唯一方法是将分隔线设置为假偏好,例如:

    <Preference
        android:layout="@layout/divider" //here I set width and a divider resource
        />
    
    <PreferenceCategory ... />
    

    这里的主要问题是我的PreferenceFragment(或其中ActionBarActivity)有一些左/右填充,这使得我添加到preferences.xml 的任何分隔符不覆盖整个宽度。

    所以我的问题是:

    • 如何摆脱图片中可以看到的默认商品分隔线?

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

10 个答案:

答案 0 :(得分:25)

PreferenceFragment

下添加此代码
    @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);

    }

答案 1 :(得分:11)

虽然有点晚了我在preff屏幕上遇到了与分频器相同的麻烦并找到了这个解决方案: 将自定义样式设置为托管活动并添加到样式:

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

它实际上与通过代码设置它相同,但你保存了一个findById,我觉得它看起来更清晰设置槽式

答案 2 :(得分:7)

完全忘了这个问题,现在会发一个答案来帮助别人。我通过在托管onResume()的活动的PreferenceFragment方法中移动代码来解决问题。我认为还有其他一些方面可以使用ListView召回非空findViewById(android.R.id.list)

public boolean mListStyled;

@Override
public void onResume() {
    super.onResume();
    if (!mListStyled) {
        View rootView = getView();
        if (rootView != null) {
            ListView list = (ListView) rootView.findViewById(android.R.id.list);
            list.setPadding(0, 0, 0, 0);
            list.setDivider(null);
            //any other styling call
            mListStyled = true;
        }
    }
}

您可以删除rootView检查,但同时您甚至可能需要检查list != null。无论如何,我没有以这种方式面对任何NPE。

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

  • list;
  • 删除填充
  • 在我的XML中添加自定义首选项:

名词

 <Preference
     android:title="divider"
     android:selectable="false"
     android:layout="@layout/preference_divider"/>

答案 3 :(得分:4)

对于PreferenceFragmentCompat,ListView不起作用。 但这就像一个魅力:

<style name="PrefsTheme" parent="PreferenceThemeOverlay.v14.Material">
    <item name="android:divider">@null</item>
    <item name="android:dividerHeight">0dp</item>
</style>

将此添加到您的应用主题:

<item name="preferenceTheme">@style/PrefsTheme</item>

答案 4 :(得分:3)

我遇到了这个确切的问题,想要在偏好类别之间但在项目本身之间不设分界线。我发现,已接受的解决方案通过从首选项中删除分隔符来满足问题1的要求,但没有解决问题2并在首选项类别之间添加分隔符。

在下面修复。 基本上覆盖您的PreferenceFragmentCompat的onCreateAdapter方法,并为其提供一个自定义PreferenceGroupAdapter,该自定义的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);
        }
    }
}

答案 5 :(得分:3)

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>

请注意,只有在上面的分隔符将allowDividerBelow设置为true并且下面的分隔符将allowDividerAbove设置为true时,分隔符才会显示在两个首选项之间。 / p>

使用代码

您还可以在onActivityCreated的{​​{1}}中使用以下方法以编程方式更改/删除分隔线:

PreferenceFragmentCompat

答案 6 :(得分:0)

如果您使用PreferenceFragment,则可以使用ListView。setDivider(null); 如果您使用PreferenceFragmentCompat,则可以使用PreferenceFragmentCompat。setDivider(Drawable divider)setDividerHeight(int height);

答案 7 :(得分:0)

新Android 24及更高版本的新解决方案( 2017年12月25日)。

我在尝试了很多方法之后找到了stackoverflow,但没有工作,或者只是工作但不能在 nestest PreferenceScreen中工作。

首先,您需要从当前显示片段中找到列表视图,然后删除分隔符:

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

其次,要在片段提交时删除分隔符,请调用上面的方法(removeDividerInCurrentFragment)以删除listview的分隔符。

确定您是否 nestest PreferenceScreen 。通过实施PreferenceActivity协议在FragmentManager.OnBackStackChangedListener中更改片段时注册侦听器:

class YourPreferenceActivity : PreferenceActivity(), FragmentManager.OnBackStackChangedListener {
    override fun onBackStackChanged() {
        this@YourPreferenceActivity.removeDividerInCurrentFragment()
    }
}

最后,注册后台会在fragmentManager.addOnBackStackChangedListener(this@ YourPreferenceActivity)中通过调用onCreate更改侦听器。并在fragmentManager.removeOnBackStackChangedListener方法中通过调用onDestroyed删除backstack更改侦听器。

祝你好运!

答案 8 :(得分:0)

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

<style name="PreferenceFragment.Material">
    <item name="android:divider">@drawable/preference_list_divider_material</item>
</style>

答案 9 :(得分:0)

(仅适用于AndroidX)

Maksim Ivanov's answer帮助了我大部分时间。但是要删除分隔符仅针对代码中创建的特定首选项,我必须这样做:

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