Как управлять разделителями в PreferenceFragment?

Я начал использовать предпочтения в PreferenceFragment. Вот что у меня есть:

my_preferences

Я пытаюсь:

  • избавиться от разделителей между элементами. Я полагаю, это можно определить из стилей, но я не могу понять, как это сделать. Я попытался получить предпочтение 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 it in) есть некоторая левая/правая прокладка, которая делает любой делитель, который я добавляю в preferences.xml не, покрывает весь ширина.

Итак, мой вопрос:

  • Как я могу избавиться от разделителей элементов по умолчанию, которые вы видите на изображении?

  • Как установить полные разделители ширины прямо над заголовками или как я могу избавиться от внутренних фрагментов/действий? Конечно, у моего макета активности нет (явного) дополнения.

Ответ 1

Если бы полностью забыл об этом вопросе, теперь опубликует ответ, чтобы помочь другим. Я решил, перемещая мой код в методе 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"/>

Ответ 2

Добавьте этот код под 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);

    }

Ответ 3

Хотя немного поздно, у меня такие же проблемы с разделителями на экране preff и нашел это решение: Установите индивидуальный стиль для активности хостинга и добавьте стиль:

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

Он фактически делает то же самое, что и устанавливать код через код, но вы сохраняете один findById, и я думаю, что он выглядит более четкими сетками прокрутки

Ответ 4

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.

В коде

Вы также можете программно изменить/удалить разделители, используя следующие методы в onActivityCreated вашего PreferenceFragmentCompat:

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

Ответ 5

Для 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>

Ответ 6

У меня была именно эта проблема, и я хотел разделить категории предпочтений, а не сами элементы. Я обнаружил, что принятое решение удовлетворило Вопрос 1, удалив разделители из элементов предпочтений, но не исправило вопрос 2 и не добавило разделители между категориями предпочтений.

Исправить ниже. В основном переопределите метод onCreateAdapter вашего PreferenceFragmentCompat и предоставьте ему собственный 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);
        }
    }
}

Ответ 7

(Только для 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)
    }
}

Ответ 8

если вы используете PreferenceFragment, вы можете использовать ListView. setDivider(null); если вы используете PreferenceFragmentCompat, вы можете использовать PreferenceFragmentCompat. setDivider(Drawable divider) или setDividerHeight(int height);

Ответ 9

Новое решение для нового API Android 24 и выше (25 декабря 2017 года).

Я нашел после многих способов использования stackoverflow, но не работал, или просто работает, но не работает в nestest PreferenceScreen.

Фрист, вам нужно найти listview из текущего отображаемого фрагмента и удалить разделитель:

private fun removeDividerInCurrentFragment() {
    [email protected](android.R.id.content)?.let {
        it.view?.findViewById<ListView?>(android.R.id.list)?.let {
            it.divider = null
            it.dividerHeight = 0
        }
    }
}

Во-вторых, чтобы удалить разделитель при совершении фрагмента, вызовите метод выше (removeDividerInCurrentFragment), чтобы удалить разделитель списка.

Конечно, если у вас nestest PreferenceScreen. Зарегистрировать слушателя, когда фрагмент изменен в вашем PreferenceActivity по протоколу FragmentManager.OnBackStackChangedListener:

class YourPreferenceActivity : PreferenceActivity(), FragmentManager.OnBackStackChangedListener {
    override fun onBackStackChanged() {
        [email protected]()
    }
}

Наконец, регистр backstack меняет прослушиватель по вызову fragmentManager.addOnBackStackChangedListener([email protected] YourPreferenceActivity) в onCreate. И удалите прослушиватель заметок назад с помощью вызова fragmentManager.removeOnBackStackChangedListener в onDestroyed.

Удачи!

Ответ 10

Вы можете переделать свой разделитель с помощью этой темы.

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