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

Mar*_*kus 44 android android-preferences

我有一个Android应用程序,其中的首选项以XML格式声明,并加载了addPreferencesFromResource.用户可以打开首选项,单击每个项目并编辑它们,所有工作.

我有一个偏好是:

        <ListPreference android:key="abc"
            android:title="@string/abc"
            android:summary="@string/cde"
            android:persistent="true"/>
Run Code Online (Sandbox Code Playgroud)

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

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

编辑

我刚刚发现两个线程(12)的想法findViewById用于访问首选项,但没有成功.它总是返回null(对我来说也是如此).

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

Mar*_*kus 37

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


该死的,它让我有几个小时,但它终于奏效了.

解决方案是未记录的电话public void onItemClick (...).它需要几个参数,并且正如此问题所指出的,它可以用于根据您要调用的元素的索引来模拟单击.

我的问题是我要调用的项目是否嵌套在XML结构中.但解决的办法很简单:添加keyPreferenceScreen你想打开的项目是:

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

</PreferenceScreen>
Run Code Online (Sandbox Code Playgroud)

你可以做到以下几点:

// 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 ); 
Run Code Online (Sandbox Code Playgroud)

对话框弹出!

获得PreferenceScreena 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" );
Run Code Online (Sandbox Code Playgroud)

  • 好的,但是请问如何在不打开主首选项屏幕的情况下只打开 ListPreference 对话框? (2认同)

Jab*_*ari 23

您可以使用扩展的ListPreference来创建对话框,然后包含您自己的公共方法,该方法调用ListPreference的受保护的showDialog方法.就像是:

public void show()
{
    showDialog(null);
}
Run Code Online (Sandbox Code Playgroud)

这样,当有多个人在评论中指出你的答案时,你就不会遇到getOrder()无法正常工作的问题.

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

  • 这是干净的方式 - 显然是最简单的方法.测试它,工作.如果您提供更详细的示例(使用扩展的首选项类,xml中的更改等),将会很高兴.我的老答案更像是"盲人领导盲人"看到这个答案. (2认同)

Dee*_*oel 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;
        }
    }
     }
 }  
Run Code Online (Sandbox Code Playgroud)


hea*_*svk 5

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

在您的PreferenceFragmentCompat中:

getPreferenceManager().showDialog(findPreference("pref_name"));
Run Code Online (Sandbox Code Playgroud)

请注意,支持首选项包存在许多问题: 非材质样式当使用打开的对话框旋转时它会崩溃