2

我的应用程序有一个 ListPreference,其条目来自网络 API。在我的 PreferenceActivity 的 onCreate() 中,我生成了一个后台线程,该线程进行 API 调用,然后在一两秒后填充 ListPreference 的条目。

如果用户在下载选项之前单击首选项屏幕上的 ListPreference 按钮,我想阻止显示首选项对话框,而是通知用户选项列表仍在加载中。

我怀疑正确的方法是覆盖 OnPreferenceClickListener,如下所示:

ListPreference dpref = (ListPreference) findPreference("debug");
String[] s = {"one", "two", "three"};
dpref.setEntries(s);
dpref.setEntryValues(s);
dpref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
    @Override
    public boolean onPreferenceClick(Preference preference) {
        Toast.makeText(this, "hi there", Toast.LENGTH_SHORT).show();
        return true;
    }
});

toast 会显示,但 ListPreference 选择器对话框也会显示。OnPreferenceClickListener文档说 onPreferenceClicktrue如果点击被处理,应该返回,但返回false具有相同的结果。

如何防止显示首选项对话框?

是否有更好的方法来处理必须在查看之前下载选项的首选项?

4

7 回答 7

6

我在同样的问题上苦苦挣扎,但在一个更简单的环境中。我的 PreferenceScreen 在 xml 文件中定义。我想自己处理一个偏好。所以我只是将“Preference”对象放入 xml 文件中,而不是“ListPreference”或“EditTextPreference”

    <Preference android:title="@string/preloadmaps1" android:summary="@string/preloadmaps2"
        android:key="preloadMaps" />

现在不再有与首选项连接的编辑器,我可以在“OnPreferenceClickListener”中自己处理编辑

于 2011-05-23T09:26:04.860 回答
5

参考关于showDialog的 android 开发者文档:

显示与此首选项关联的对话框。这通常在单击首选项时自动启动。如果您需要在其他事件上显示对话框,请调用此方法。

因此,当单击首选项会自动调用 showDialog() 时,如果您想控制以防止在单击首选项上显示对话框,则需要实现自定义首选项,如下所示,

public class MyPreference extends ListPreference {
    private Context context;

    // a flag to control show dialog
    private boolean showDialog = false;

    public MyPreference(Context context) {
        super(context);
        this.context = context;
    }

    public MyPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;       
    }

    @Override
    protected void showDialog(Bundle state) {        
        if (showDialog) {
            // show dialog 
            super.showDialog(state);
        } else {
            // if you don't want to show a dialog when click preference
            return;
        } /* end of if */
    }
}
于 2012-06-27T16:09:27.513 回答
2

我不确定为什么你的方法不起作用,但这里有一个快速的解决方法:

为应该下载的每个首选项添加存根首选项。您可以以任何您想要的方式自定义您的点击操作。不会显示任何对话框。

当您的偏好选项准备就绪时,删除旧的 Preference(按其名称)并使用您的选项创建新的 ListPreference(与刚刚删除的名称相同)。

这将使您可以灵活地为您需要的任何事件添加任何类型的自定义首选项。尽管如您所见,需要一些额外的编码。

于 2011-01-12T00:37:26.580 回答
1

我知道这是一个老问题,但仍然没有答案如何取消这些对话框。因此,这是取消首选项对话框的方法:

dpref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
    @Override
    public boolean onPreferenceClick(Preference preference) {
        ((ListPreference)preference).getDialog().dismiss();   <<< This will do it
        Toast.makeText(this, "hi there", Toast.LENGTH_SHORT).show();
        return true;
    }
});

但是,与其关闭对话框,不如隐藏它以便稍后在从 web 加载选项列表时显示它。这样做:

dpref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
    @Override
    public boolean onPreferenceClick(Preference preference) {
        ((ListPreference)preference).getDialog().hide();   <<< This will just hide the dialog and you still can show it later
        Toast.makeText(this, "hi there", Toast.LENGTH_SHORT).show();
        return true;
    }
});

稍后,当加载选项列表时:

...
dpref.setEntries(<array_of_options_here>);
dpref.getdialog().show();  <<< If you dismiss the dialog earlier and not hide it, then getDialog() returns null here 
...
于 2014-12-02T14:46:34.620 回答
0

我会使用一个代理Activity(样式为对话框)来下载首选项并在PreferenceActivity完成后启动实际的。

于 2011-01-12T04:43:08.763 回答
0

您可以onResume()在您的偏好活动中执行以下操作:

  • 开始async call...
    • 将首选项设置为禁用,并提示正在获取值
    • 获取值的网络(无论是没有值还是总是) - 异步,因此它不会停止恢复
    • 使用您获取的值更新首选项条目
    • 启用首选项并显示默认提示

如果这样做的缺点是,您的首选项要么会过于频繁地更新(例如,总是在您的首选项屏幕开始时),但是这样您就可以处理网络调用的结果产生一个列表的情况,其中之前选择的值不是不再存在(例如,向用户显示一个对话框,其中说他的选择不再可用)。

此外,这是一项相当复杂的任务(因为您必须定义 a Handler,因为异步执行存在于另一个线程中......)

它看起来像这样(假设你在你PreferenceActivity

import android.os.Handler;
import android.os.AsyncTask;
import android.os.Message;

public class xyz extends PreferenceActivity {
    ...
    // define a handler to update the preference state
    final Handler handler = new Handler() {
        public void handleMessage( Message msg ) {
            ListPreference dpref = (ListPreference) getPreferenceManager().findPreference("debug");
            dpref.setEnabled( msg.getData().getBoolean("enabled") );
            dpref.setSummary( msg.getData().getString("summary") );
        }
    };



    private class updatePref extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... arg) {

            Message msg = handler.obtainMessage();
            Bundle data = new Bundle();
            data.putBoolean("enabled", false ); // disable pref
            data.putString("summary", "Getting vals from network..." ); // set summary
            msg.setData( data );
            handler.sendMessage(msg); // send it do the main thread

            ListPreference dpref = (ListPreference) getPreferenceManager().findPreference("debug");


            String values[];
            // call network function and let it fill values[]

            // do things according to the returned values, 
            // eg check if there are any, check if the user has 
            // already selected one, display a message if the 
            // user has selected one before but the values do not
            // contain them anymore, ...

            // set the new values     
            dpref.setEntries(values);
            dpref.setEntryValues(values);

            data.putBoolean("enabled", true ); // enable pref
            data.putString("summary", "Please choose" ); // set summary
            msg.setData( data );
            handler.sendMessage(msg); // send it do the main thread

            return null;
        }
    }

    public void onResume() {
        ....
        new updatePref().execute();

    }

}

当然你可以new updatePref().execute()在任何地方调用,所以你也可以将它绑定到 aButtononCreate()任何地方(无需在 中执行此操作onResume())。

于 2011-01-29T11:32:15.507 回答
0

收藏的另一种方式。我相信它仅适用于android.support.v7.preference 库PreferenceFragmentCompat(在我的情况下为 27.1.1)。这是一个例子:

public class PrefsFragment extends PreferenceFragmentCompat implements PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback {

    private static final int REQUEST_VIEW_PREFERENCE = 1;

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_VIEW_PREFERENCE && resultCode == Activity.RESULT_OK) {
            Preference preference = findPreference("preference_key");
            getPreferenceManager().showDialog(preference)
        }
    }

    @Override
    public Fragment getCallbackFragment() {
        this;
    }

    @Override
    public boolean onPreferenceDisplayDialog(PreferenceFragmentCompat caller, Preference pref) {
        if (pref.getKey().equals("preference_key")) {
            if (canBeOpened(pref)) {
                return false;
            } else {
                // show a fragment loading data with requestCode == REQUEST_VIEW_PREFERENCE
                ...
                return true;
            }
        }
    }

    private boolean canBeOpened(Preference pref) {
        // check whether a preference can be clicked
        ...
    }
}

Preference.java如果我正确理解了源代码,则OnPreferenceClickListener返回true仅适用于基于意图的首选项,但如果要显示对话框则将被忽略。

在上面的示例中,OnPreferenceDisplayDialogCallback用于防止显示首选项对话框。从 中返回实现此接口的片段很重要getCallbackFragment()

于 2018-06-01T06:36:26.300 回答