Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/227.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 从(子)首选项屏幕返回时更新首选项活动中的现有首选项_Android_Preferences_Invalidation_Preferenceactivity - Fatal编程技术网

Android 从(子)首选项屏幕返回时更新首选项活动中的现有首选项

Android 从(子)首选项屏幕返回时更新首选项活动中的现有首选项,android,preferences,invalidation,preferenceactivity,Android,Preferences,Invalidation,Preferenceactivity,我有一个带有一系列(子)首选屏幕的首选活动。每个这样的(子)首选项屏幕代表一个帐户,并将帐户用户名作为其标题 PreferenceScreen root = mgr.createPreferenceScreen(this); for (MyAccountClass account : myAccounts) { final PreferenceScreen accScreen = mgr.createPreferenceScreen(this); accScreen.setTi

我有一个带有一系列(子)首选屏幕的首选活动。每个这样的(子)首选项屏幕代表一个帐户,并将帐户用户名作为其标题

PreferenceScreen root = mgr.createPreferenceScreen(this);
for (MyAccountClass account : myAccounts) {
    final PreferenceScreen accScreen = mgr.createPreferenceScreen(this);

    accScreen.setTitle(account.getUsername());

    // add Preferences to the accScreen
    // (for instance a "change username"-preference)
    ...

    root.add(accScreen);
}
当用户进入sub PreferenceScreen并编辑帐户用户名时,我希望外部PreferenceScreen为所讨论的帐户更新其PreferenceScreen标题

我试着添加

usernamePref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        accScreen.setTitle(newValue.toString());
        return true;
    }
});
…但是accScreen.setTitle似乎不会在外部首选项屏幕上生效。我注意到调用
onContentChanged()
实际上可以让它工作,但我意识到这可能不是最好的方式

我想我应该在某个地方的某个视图上调用
postInvalidate()
,但我真的不知道该在什么视图上以及什么时候执行

可能和我遇到了同样的问题


感谢您的帮助。

遇到同样的问题,但onContentChanged()对我不起作用。我的问题是首选项屏幕从根本上看不止一个级别

按照您的示例,如果您首先创建了“Accounts”首选项屏幕,然后在该屏幕下添加了每个account PreferenceScreen对象。像这样:

Root Screen -> "Accounts" screen -> "foo@example.com" screen -> edit username -> edit password -> etc... -> "bar@example.com" screen -> "baz@example.com" screen -> etc... 根屏 ->“帐户”屏幕 -> "foo@example.com“屏幕 ->编辑用户名 ->编辑密码 ->等等。。。 -> "bar@example.com“屏幕 -> "baz@example.com“屏幕 ->等等。。。 如果用户编辑用户名并单击“保存”,则调用PreferenceActivity.onContentChanged()似乎只会影响根PreferenceScreen的直接后代。第三代屏幕的标题和摘要没有被重新绘制,仍然反映了旧的价值观

查看onContentChanged()的代码,看起来它只是将根屏幕重新绑定到ListActivity的ListView,尽管我认为后续的首选项屏幕从未绑定到ListView(是吗?),因此我们无法手动重新绑定任何内容


我能想到的唯一解决办法是将子菜单创建为独立的首选项活动,而不是首选项屏幕,这样我们就可以有意识地在直接祖先上调用onContentChanged()。但这比目前的解决方案更为困难。有什么想法吗?

我找到了解决办法。我有这样一个层次结构,每个层次结构都是一个首选屏幕:

main settings
  -> users list
    -> user1 settings
    -> user2 settings
    ...
在用户列表中,子屏幕的标题取决于用户设置。现在,当我创建用户列表时,我将列表适配器存储到PreferenceActivity中的一个变量

 PreferenceScreen usersListScreen = ...
 userScreenListAdapter = (BaseAdapter)usersListScreen.getRootAdapter();
现在,当编辑userX设置时,我会在usersListScreen中设置标题,然后调用:

userScreenListAdapter.notifyDataSetChanged();

它会更新列表界面,并且更改是可见的。

这对我来说很有效,你必须抓住首选项屏幕的基本对话框,然后从那里设置标题,非常简单

somePrefScreen.getDialog().setTitle("Whatever you want");

首选项活动#onContentChanged()
将刷新整个屏幕,出现一些闪烁效果

但是,您可以使用
首选项活动#onPreferenceTreeClick(…)
方法有选择地对给定的首选项实现相同的目标

注意,这个方法现在已经被弃用:考虑使用这似乎解决了很多自定义偏好的问题(我还没有测试自己)。对于较旧的SDK,没有可用性

public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {

Log.v(TAG, "onSharedPreferenceChanged(...," + key + ")");

if (key.equals("myPref")) {
    onPreferenceTreeClick(getPreferenceScreen(), getPreferenceManager().findPreference("myPref"));
    Log.v(TAG, "Do whatever else you need...");
}

//onContentChanged();    // this could be used but occurs screen flickering
}
我只是把

((BaseAdapter)getPreferenceScreen().getRootAdapter()).notifyDataSetChanged();

在更新我的父项首选项的摘要之后。

notifyDataSetChanged()是正确的解决方案。但我想为所有首选项屏幕添加递归迭代器,因为我在查找首选项的真正父项时遇到了问题。对于复杂的首选项结构,我建议使用以下杀手代码:

private void updateAll_PrefereneScreens(PreferenceGroup group) {
    if (group instanceof PreferenceScreen) {
        BaseAdapter adapter = (BaseAdapter) ((PreferenceScreen) group).getRootAdapter();
        adapter.notifyDataSetChanged();
    }
    for (int i=0; i<group.getPreferenceCount(); i++) {
        Preference pref = group.getPreference(i);
        if (pref instanceof PreferenceGroup) {
            updateAll_PrefereneScreens((PreferenceGroup) pref);
        }
    }
}

这可能是一个迟来的答案,但仍然。。。我现在就在上面:)

我实现它的方法是,您可以连接到其生命周期的首选项FragmentCompatonResume()方法,并通过重置其值手动更新所需字段

注意:在本例中,我还跟踪编辑的首选项的索引,只是为了避免重置每个索引

    // let's say you need to update title of the parent screen
    // when back from sub-screen(s) edition

    private int edited = -1;

    // this gets called everytime you get back to the parent screen
    @Override
    public void onResume ()
    {
        super.onResume();
        if ( edited != -1 )
        {
            PreferenceScreen root = getPreferenceScreen();
            Preference preference = root.getPreference( edited );

            if ( preference != null )
            {
                String updatedValue = getPreferenceManager()
                .getSharedPreferences()
                .getString( "your-preference-key", "your-default-value" );

                preference.setTitle( updatedValue );
            }

            edited = -1;
        }
    }

    // everytime you are about to navigate to a sub-screen 
    @Override
    public boolean onPreferenceTreeClick ( Preference preference )
    {
        // beware to save it first
        if ( preference instanceof MySubScreenPreference )
        {
            edited = preference.getOrder();
        }

        return super.onPreferenceTreeClick( preference );
    }
按照文件规定:

恢复

当片段对用户可见并正在运行时调用。这通常和包含活动生命周期的Activity.onResume相关联

好的是,它当然也适用于FragmentManager的事务


希望这有帮助,快乐编码!:)

我设法让它工作的方法是重载onResume方法并在其中重建UI。aioobe,你能展示一些示例代码来说明你是如何做到这一点的吗?哇,听起来不错。我目前还没有安装android SDK,但我相信你的话,它是有效的。伟大的这也将在调用后重置对首选项片段(例如侦听器)中的首选项所做的所有更改!(或者换句话说,从调用这个直到它完成重建视图所做的更改将丢失:))好吧,猜猜看。。。他们将首选项从支持库中删除了!!因此,对于较旧的API级别,您仍然必须使用PreferenceActivity:(支持库中没有getRootAdapter)
findPreference("KEY").setSummary(str);
updateAll_PrefereneScreens(getPreferenceScreen());
    // let's say you need to update title of the parent screen
    // when back from sub-screen(s) edition

    private int edited = -1;

    // this gets called everytime you get back to the parent screen
    @Override
    public void onResume ()
    {
        super.onResume();
        if ( edited != -1 )
        {
            PreferenceScreen root = getPreferenceScreen();
            Preference preference = root.getPreference( edited );

            if ( preference != null )
            {
                String updatedValue = getPreferenceManager()
                .getSharedPreferences()
                .getString( "your-preference-key", "your-default-value" );

                preference.setTitle( updatedValue );
            }

            edited = -1;
        }
    }

    // everytime you are about to navigate to a sub-screen 
    @Override
    public boolean onPreferenceTreeClick ( Preference preference )
    {
        // beware to save it first
        if ( preference instanceof MySubScreenPreference )
        {
            edited = preference.getOrder();
        }

        return super.onPreferenceTreeClick( preference );
    }