Как открыть или смоделировать щелчок по настройке Android, созданной с помощью XML, программно?

У меня есть приложение для Android с настройками, объявленными в XML, загружено с addPreferencesFromResource, Пользователь может открывать настройки, нажимать на каждый элемент и редактировать их, все работает.

У меня есть одно предпочтение:

        <ListPreference android:key="abc"
            android:title="@string/abc"
            android:summary="@string/cde"
            android:persistent="true"/>

Как автоматически отобразить диалоговое окно настроек для пользователя (без необходимости переходить на экран настроек и нажимать на него?).

Я старался ( (android.preference.DialogPreference) prefMgr.findPreference( "abc" )).showDialog(null), но это говорит, что это защищенный метод...? Называется это из моей основной деятельности (которая является PreferenceActivity), именно поэтому это, очевидно, не может работать. А как еще?

РЕДАКТИРОВАТЬ

Я только что нашел две темы ( 1 и 2) с идеей использовать findViewById чтобы получить доступ к предпочтениям, но безуспешно. Он всегда возвращает ноль (тоже для меня).

Похоже, что на самом деле нет возможности сделать это из кода.

7 ответов

Решение

Вы могли бы расширить ListPreference для создания своего диалога, а затем включить свой собственный открытый метод, который вызывает защищенный метод showDialog ListPreference. Что-то вроде:

public void show()
{
    showDialog(null);
}

Таким образом, вы не столкнетесь с проблемой, когда getOrder() не работает, когда есть PreferenceGroups, так как несколько человек указали в комментариях на ваш ответ.

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

Смотрите новый принятый ответ для более чистого подхода! Это работало, но не совсем чистый способ сделать это.


Черт возьми, это дало мне несколько часов, но наконец-то работает.

Решение - недокументированный звонок public void onItemClick (...), Он принимает несколько аргументов, и, как указывает этот вопрос, его можно использовать для имитации щелчка в соответствии с индексом элемента, который вы хотите вызвать.

Моя проблема заключалась в том, что элемент, который я хочу вызвать, глубоко вложен в XML-структуру. Но решение очень простое: добавить key к PreferenceScreen элемент, который вы хотите открыть, находится в:

<PreferenceScreen
    android:key="pref_key"
    ....
    />
    <ListPreference android:key="abc"
        android:title="@string/abc"
        android:summary="@string/cde"
        android:persistent="true"/>

</PreferenceScreen>

А вы можете просто следующее:

// the preference screen your item is in must be known
PreferenceScreen screen = (PreferenceScreen) findPreference("pref_key");

// the position of your item inside the preference screen above
int pos = findPreference("abc").getOrder();

// simulate a click / call it!!
screen.onItemClick( null, null, pos, 0 ); 

И Диалог всплывает!

Было бы неплохо получить PreferenceScreen Preference в (так что вам не нужно знать, где ваш Preference находится в), потому что перемещение предпочтения / изменение XML может молча нарушить автоматический диалог и может не быть замечено (если не проверено).

Для этого я написал функцию, которая будет искать во всех настройках и возвращать PreferenceScreen ваши предпочтения включены, поэтому вам не нужно иметь свой PreferenceScreen ключ!

private PreferenceScreen findPreferenceScreenForPreference( String key, PreferenceScreen screen ) {
    if( screen == null ) {
        screen = getPreferenceScreen();
    }

    PreferenceScreen result = null;

    android.widget.Adapter ada = screen.getRootAdapter();
    for( int i = 0; i < ada.getCount(); i++ ) {
        String prefKey = ((Preference)ada.getItem(i)).getKey();
        if( prefKey != null && prefKey.equals( key ) ) {
            return screen;
        }
        if( ada.getItem(i).getClass().equals(android.preference.PreferenceScreen.class) ) {
            result = findPreferenceScreenForPreference( key, (PreferenceScreen) ada.getItem(i) );
            if( result != null ) {
                return result;
            }
        }
    }

    return null;
}

private void openPreference( String key ) {
    PreferenceScreen screen = findPreferenceScreenForPreference( key, null );
    if( screen != null ) {
        screen.onItemClick(null, null, findPreference(key).getOrder(), 0);
    }
}

// With this, you can call your `Preference` like this from code, you do
// not even have to give your PreferenceScreen a key!
openPreference( "abc" );

Если вы используете библиотеку поддержки, вы можете легко открыть диалог с помощью PreferenceManager.showDialog (Preference).

В вашем PreferenceFragmentCompat:

getPreferenceManager().showDialog(findPreference("pref_name"));

Обратите внимание, что пакет поддержки предпочтений имеет много проблем: нематериальное оформление и происходит сбой при повороте с открытым диалогом.

 PreferenceScreen preferenceScreen  = (PreferenceScreen) findPreference("pref_key");
    final ListAdapter listAdapter = preferenceScreen.getRootAdapter();
         EditTextPreference editPreference = (EditTextPreference)   findPreference("set_password_preference");

    final int itemsCount = listAdapter.getCount();
    int itemNumber;
    for (itemNumber = 0; itemNumber < itemsCount; ++itemNumber) {
        if (listAdapter.getItem(itemNumber).equals(editPreference)) {
            preferenceScreen.onItemClick(null, null, itemNumber, 0);
            break;
        }
    }
     }
 }  

Улучшение deepak goelответ:

private void openPreference(String key) {
    PreferenceScreen preferenceScreen = getPreferenceScreen();
    final ListAdapter listAdapter = preferenceScreen.getRootAdapter();

    final int itemsCount = listAdapter.getCount();
    int itemNumber;
    for (itemNumber = 0; itemNumber < itemsCount; ++itemNumber) {
        if (listAdapter.getItem(itemNumber).equals(findPreference(key))) {
            preferenceScreen.onItemClick(null, null, itemNumber, 0);
            break;
        }
    }
}

Если вы используете библиотеку предпочтений AndroidX, это довольно просто.

public class CustomPreferenceFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        addPreferencesFromResource(R.xml.your_preference);
        DialogPreference dialogPreference = (DialogPreference) findPreference("your_preference_key");
        onDisplayPreferenceDialog(dialogPreference);
    }
}

Привет друзья попробуйте этот код в работает нормально

getPreferenceManager().findPreference("YOUR PREF_KEY").setOnPreferenceClickListener(new OnPreferenceClickListener()
        {
            public boolean onPreferenceClick(Preference preference)
            {

                //your code here
                return true;
            }
        });

Подожди, ты тоже можешь сделать что-то подобное

Preference p=findPreference("settings_background_color");
p.setOnPreferenceClickListener(new OnPreferenceClickListener() {

    @Override
    public boolean onPreferenceClick(Preference preference) {

        int color=PreferenceManager.getDefaultSharedPreferences(ALifePatternsWallpaperSettings.this).getInt("settings_background_color", Color.BLACK);
        new ColorPickerDialog(ALifePatternsWallpaperSettings.this, ALifePatternsWallpaperSettings.this, "settings_background_color", color, Color.BLACK).show();
        return true;
    }
});
Другие вопросы по тегам