如何以编程方式打开或模拟用XML创建的Android Preference上的点击?

时间:2011-01-26 14:50:12

标签: android android-preferences

我有一个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)调用它,这就是它显然无法工作的原因。但是怎么回事?

修改

我刚刚找到了两个主题(12),并希望使用findViewById来访问首选项,但没有成功。它总是返回 null (也适合我)。

看起来似乎没有可能从代码中做到这一点。

8 个答案:

答案 0 :(得分:37)

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


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

解决方案是未记录的电话public void onItemClick (...)。它需要几个参数,正如this question所指出的,它可以用来根据你想要调用的元素的索引来模拟一次点击。

我的问题是我要调用的项目是否嵌套在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" );

答案 1 :(得分:21)

您可以使用扩展的ListPreference来创建对话框,然后包含您自己的公共方法,该方法调用ListPreference的受保护的showDialog方法。类似的东西:

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

通过这种方式,当有多个人在评论中指出你的答案时,你不会遇到getOrder()无法正常工作的问题。

这可以使用任何具有受保护的showDialog方法的首选项类型来完成。

答案 2 :(得分: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;
        }
    }
     }
 }  

答案 3 :(得分:4)

如果您使用支持库,则可以使用PreferenceManager.showDialog(Preference)轻松打开对话框。

在PreferenceFragmentCompat中:

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

请注意,支持首选项包有许多问题: non-material stylingit crashes when rotated with an open dialog

答案 4 :(得分:3)

改善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;
        }
    }
}

答案 5 :(得分:0)

如果您使用的是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);
    }
}

答案 6 :(得分:-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;
    }
});

答案 7 :(得分:-1)

嗨朋友们可以试试这段代码

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

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