Удалить / скрыть настройки с экрана


134

У меня есть деятельность, которая расширяет PreferenceActivity. Я загружаю настройки из файла XML. Но в некоторых случаях мне нужно полностью скрыть одно из предпочтений на экране в зависимости от состояния моего приложения. Есть метод setEnabled, но это не совсем то, что я хочу. Я хочу полностью удалить это предпочтение с экрана. Является ли это возможным ?

Ответы:


171

Да, если у вас есть ссылка как на Preference, так и на его родитель (а PreferenceCategory, или PreferenceScreen)

myPreferenceScreen.removePreference(myPreference);

Большой! Спасибо! Работает и имеет смысл
Бостон

Я мог бы ответить на свой вопрос через это? stackoverflow.com/a/4704360/956975
Мариенке

2
К сожалению, это навсегда удаляет предпочтения. Можно ли просто это скрыть?
Дмитрий

Это также не работает для меня. Предпочтение остается!
Дмитрий

@Dmitry Вы можете просто затенить это сsetEnabled()
JakeD

212

Если вы находитесь в Preferenceпределах PreferenceCategory, вы должны сделать это:

XML:

<PreferenceCategory
    android:key="category_foo"
    android:title="foo">

    <CheckBoxPreference
        android:key="checkPref" />

Ява:

CheckBoxPreference mCheckBoxPref = (CheckBoxPreference) findPreference("checkPref");
PreferenceCategory mCategory = (PreferenceCategory) findPreference("category_foo");
mCategory.removePreference(mCheckBoxPref);

5
Чтобы быть справедливым, ответ выше говорит о том, что вам нужен родитель PreferenceCategory.
Мэтт

49

В случае, когда предпочтение является прямым потомком экрана предпочтений, вот некоторый автономный код:

PreferenceScreen screen = getPreferenceScreen();
Preference pref = getPreferenceManager().findPreference("mypreference");
screen.removePreference(pref);

4
Это не будет работать, если предпочтение находится внутри категории. Вы должны findPreferenceдля категории, и удалить предпочтение из категории
MBH

1
@MBH: Спасибо за упоминание этого предостережения!
1 ''

9

Если вы хотите что-то, что будет динамически изменять префиксы, например, в SwitchPreference, я обнаружил, что лучший способ - поместить все мои подопции в контейнеры двух категорий. Сначала вы увидите все, а затем удалите ненужные биты. Умный момент: вы просто запускаете пересоздание, когда что-то меняется, и тогда вам не нужно ничего создавать вручную или беспокоиться о том, чтобы вернуть вещи в правильном порядке.

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  addPreferencesFromResource(R.xml.preferences);
  PreferenceCategory prefCatOne= (PreferenceCategory)findPreference("prefCatOne");
  PreferenceCategory prefCatTwo= (PreferenceCategory)findPreference("prefCatTwo");
  SwitchPreference mySwitchPref= (SwitchPreference)findPreference("mySwitchPref");
  PreferenceScreen screen = getPreferenceScreen();
  if (mySwitchPref.isChecked()) {
    screen.removePreference(prefCatOne);
  } else {
    screen.removePreference(prefCatTwo);
  }
}

public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
    if (key.equals("mySwitchPref")) {
        this.recreate();
    }
}

Единственный недостаток, который я могу видеть с этим, - это вспышка, поскольку экран воссоздан с нуля.


Случай не работает, по крайней мере, в 22. Но изменение его на Предпочтение (даже если это группа предпочтений) работает.
Роб

Роб, я только что протестировал приведенный выше код в AVD API22, и он работает просто отлично. Убедитесь, что ваши предпочтения XML-контента соответствуют вашему коду. Для приведенного выше примера SwitchPreference может быть где угодно, но вам нужно, чтобы PreferenceCategorys были прямыми потомками PreferenceScreen.
Джеймс

Я только что получил категорию в качестве предпочтения, без приведения и удалил ее. Работал.
Роб

8

В вашем XML-файле:

<PreferenceScreen 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:key="preferenceScreen">

    <PreferenceCategory
        android:key="personalisation"
        android:title="your title here">

        <ThemedPreference
            android:key="animation" />

</PreferenceScreen>

В вашем коде:

PreferenceScreen pPreferenceScreen = (PreferenceScreen) findPreference("preferenceScreen");

PreferenceCategory pCategory = (PreferenceCategory) findPreference("personalisation");
ThemedPreference pThemePref = (ThemedPreference) findPreference("animation");

pPreferenceScreen.removePreference(pCategory); //remove category
pCategory.removePreference(pThemePref);   // remove preference

8

Если вы используете PreferenceFragmentCompat, вы можете установить видимость в xml.

Настройки в вашем xml будут автоматически преобразованы в версии AppCompat. Затем вы можете использовать атрибут app: isPreferenceVisible в своем XML

preferences.xml

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <CheckBoxPreference
        android:defaultValue="false"
        android:key="show.navigation"
        android:title="Show navigation"
        app:isPreferenceVisible="false" />

...

Атрибут задокументирован по адресу https://developer.android.com/guide/topics/ui/settings/components-and-attributes.

Добавление PreferenceFragmentCompatзадокументировано по адресу https://developer.android.com/guide/topics/ui/settings/#inflate_the_hierarchy

Пример:

public class MySettingsActivity extends AppCompatActivity {

    public static class MySettingsFragment extends PreferenceFragmentCompat {
        @Override
        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
            setPreferencesFromResource(R.xml.preferences, rootKey);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.settings_container, new MySettingsFragment())
                .commit();
    }
} 

5

Я рекомендую использовать предпочтение v7, у него есть setVisible()метод. Но я еще не пробовал. Соответственно вы должны использовать PreferenceFragmentвместо PreferenceActivity.


Принятый ответ не будет работать для V7. Использование setVisible работает для V7
m12lrpv

3

В файле XML вы можете сделать скрытые предпочтения, оставив теги заголовка и резюме пустыми.

<EditTextPreference
    android:defaultValue="toddlerCam"
    android:key="save_photo_dir"
/>

Это идеальный ответ для меня. Я искал это. Спасибо!
劇場 期 劇場

2

Вот общий способ сделать это, который работает независимо от того, находится ли предпочтение под PreferenceCategoryили PreferenceScreen.

private void removePreference(Preference preference) {
    PreferenceGroup parent = getParent(getPreferenceScreen(), preference);
    if (parent == null)
        throw new RuntimeException("Couldn't find preference");

    parent.removePreference(preference);
}

private PreferenceGroup getParent(PreferenceGroup groupToSearchIn, Preference preference) {
    for (int i = 0; i < groupToSearchIn.getPreferenceCount(); ++i) {
        Preference child = groupToSearchIn.getPreference(i);

        if (child == preference)
            return groupToSearchIn;

        if (child instanceof PreferenceGroup) {
            PreferenceGroup childGroup = (PreferenceGroup)child;
            PreferenceGroup result = getParent(childGroup, preference);
            if (result != null)
                return result;
        }
    }

    return null;
}


0

Вы можете сделать это двумя способами:

1.Если вы используете библиотеку поддержки, вы можете построить карту дерева предпочтений и их родителей, а затем удалить предпочтение с помощью его родителя. Вот функция для генерации такой карты:

public static Map<Preference, PreferenceGroup> buildPreferenceParentTree(@NonNull final PreferenceScreen preferenceScreen) {
    final Map<Preference, PreferenceGroup> result = new HashMap<>();
    final Stack<PreferenceGroup> curParents = new Stack<>();
    curParents.add(preferenceScreen);
    while (!curParents.isEmpty()) {
        final PreferenceGroup parent = curParents.pop();
        final int childCount = parent.getPreferenceCount();
        for (int i = 0; i < childCount; ++i) {
            final Preference child = parent.getPreference(i);
            result.put(child, parent);
            if (child instanceof PreferenceGroup)
                curParents.push((PreferenceGroup) child);
        }
    }
    return result;
}
  1. Если вы используете новый API настроек android-x, вы можете просто установить видимость, используя для этого функцию setVisible .

Согласно документации и чаю ответ setVisible() доступен начиная с версии 24.1.0 библиотеки поддержки.
JJD

Вы смотрели на то, что я написал? Я специально написал, что теперь это возможно ... Кроме того, первое решение помогает с удалением, которое немного отличается от сокрытия ..
Разработчик Android

Да, я прочитал ваш ответ. Я имел в виду ваш второй пункт. Читается так, как будто setVisibile()метод доступен с Android-X, который я пытался уточнить. Без обид, пожалуйста.
JJD

Android-X заменяет все библиотеки поддержки. Не будет никаких новых версий библиотеки поддержки, поскольку мы знаем их.
разработчик Android

Верный. Я в курсе этого . Тем не менее, люди, которые застряли в предыдущих версиях, могут использовать этот метод.
JJD

0

Если вы хотите оценить, и на основе этой маски, альтернативой может быть

SwitchPreference autenticacionUsuario = 
    (SwitchPreference) findPreference("key_autenticacion_usuario");

final EditTextPreference Username = 
    (EditTextPreference) findPreference("key_username_mqtt");
final EditTextPreference Password = 
    (EditTextPreference) findPreference("key_password_mqtt");

if (!autenticacionUsuario.isChecked()) {
    PreferenceCategory preferenceCategory = 
        (PreferenceCategory) findPreference("category_mqtt");
    preferenceCategory.removePreference(Username);
    preferenceCategory.removePreference(Password);
}

Все это должно быть в пределах

public static class PrefsFragment extends PreferenceFragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

1
Извините, но это английский сайт. Вы можете ответить на английском?
Дэйв Швайсгут

Конечно, я также
хотел

3
@GustavoEduardoBelduma, тогда вам может понадобиться прочитать этот meta.stackoverflow.com/a/297680/545026
Лео поддерживает Монику Челлио

0

Если вы делаете то, что, я думаю, вы пытаетесь сделать (потому что я пытаюсь сделать это сейчас), возможно, было бы лучше включить / отключить настройку. Потому что его удаление убирает его с экрана настроек, и вы не сможете добавить его туда, где вы хотите, если вы сделали экран программным способом.

pref.setEnabled (ложь); pref.setEnabled (истина);

хотя это может быть устаревшим. Это работает для варианта использования, который я сейчас рассматриваю.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.