46

我有一个带有在 XML 中声明的首选项的 android 应用程序,加载了addPreferencesFromResource. 用户可以打开首选项,单击每个项目并对其进行编辑,一切正常。

我的一个偏好是:

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

如何自动向用户显示首选项对话框(无需用户转到首选项屏幕并单击它?)。

我试过( (android.preference.DialogPreference) prefMgr.findPreference( "abc" )).showDialog(null)了,但据说这是一种受保护的方法......?从我的主要活动(即 a PreferenceActivity)中调用它,这就是它显然无法工作的原因。但还能怎么办?

编辑

我刚刚找到了两个线程(12findViewById用于访问首选项,但没有成功。它总是返回null(对我也一样)。

看起来真的不可能从代码中做到这一点。

4

8 回答 8

37

请参阅新接受的答案以获得更清洁的方法!这是有效的,但不是真正干净的方式。


该死的,它花了我几个小时,但它终于奏效了。

解决方案是无证调用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让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" );
于 2011-02-01T23:08:50.447 回答
23

You could have extended ListPreference to create your dialog, then included your own public method that calls the protected showDialog method of ListPreference. Something like:

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

This way you won't run into the issue of getOrder() not working when there are PreferenceGroups as several people have pointed out in the comments your answer.

This can be done with any preference types that has a protected showDialog method.

于 2012-11-16T09:53:12.993 回答
10

If you use the support library you can open a dialog easily with PreferenceManager.showDialog(Preference).

In your PreferenceFragmentCompat:

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

Note that support preference package has many issues: non-material styling and it crashes when rotated with an open dialog.

于 2016-01-26T13:22:41.453 回答
8
 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;
        }
    }
     }
 }  
于 2013-07-29T09:02:45.287 回答
4

Improving deepak goel's answer:

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;
        }
    }
}
于 2015-09-29T20:16:27.357 回答
0

If you're using AndroidX Preference library, it is quite simple.

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);
    }
}
于 2020-10-02T18:59:29.127 回答
-1

等等,你也可以做这样的事情

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;
    }
});
于 2011-08-31T13:13:07.620 回答
-2

hi friends try this code in works fine

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

                //your code here
                return true;
            }
        });
于 2012-11-19T12:34:52.550 回答