Как открыть или смоделировать щелчок по настройке Android, созданной с помощью XML, программно? - PullRequest
43 голосов
/ 26 января 2011

У меня есть приложение для 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 для доступапредпочтение, но безуспешно.Он всегда возвращает null (тоже для меня).

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

Ответы [ 7 ]

37 голосов
/ 02 февраля 2011

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


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

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

Моя проблема заключалась в элементе Iхочу позвонить глубоко вложен в 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 a 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" );
22 голосов
/ 16 ноября 2012

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

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

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

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

8 голосов
/ 29 июля 2013
 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;
        }
    }
     }
 }  
4 голосов
/ 26 января 2016

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

В вашем PreferenceFragmentCompat:

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

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

3 голосов
/ 29 сентября 2015

Улучшение 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;
        }
    }
}
0 голосов
/ 19 ноября 2012

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

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

                //your code here
                return true;
            }
        });
0 голосов
/ 31 августа 2011

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

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