如何强制将子 PreferenceScreen 包含在 Fragment 布局中 (Android)

How to force sub PreferenceScreen to be contained in Fragment layout (Android)

我对 Android 的偏好系统还很陌生,目前遇到了一个问题。

根据 Android 指南 (http://developer.android.com/guide/topics/ui/settings.html) 的建议,我使用 Preference Fragment。因此,我的 SettingsActivity 包含一些内容(headers,如标题、标签等)和下面的 PreferenceFragment。

问题是,当我单击与 "sub" PreferenceScreen 关联的首选项时,"new preference screen" 不遵循我的片段布局,而是填充了整个 activity。

这是一个示例:假设我有一个调用 addPreferenceFromResource(R.xml.preferences) 的 PreferenceFragment。 preferences.xml 确实包含一个 "Change password" 首选项,这是一个包含 3 个 TextEditPreference 的 PreferenceScreen。

preferences.xml

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">   
    <EditTextPreference android:title="@string/pref_one"/>
    <EditTextPreference android:title="@string/pref_two"/>

    <PreferenceScreen android:title="@string/pref_change_password">

        <EditTextPreference android:title="@string/pref_current_pass"
            android:inputType="textPassword"
            android:hint="@string/hint_current_password" />

        <EditTextPreference android:title="@string/pref_new_pass"
            android:inputType="textPassword"
            android:hint="@string/hint_new_password" />

        <EditTextPreference android:title="@string/pref_confirm_new_pass"
            android:inputType="textPassword"
            android:hint="@string/hint_confirm_new_password" />

    </PreferenceScreen>
</PreferenceScreen>

因此,当我单击 PreferenceScreen 时,它会执行以下操作:

但我希望它这样做:

我该怎么做? 预先感谢您的回答!

好的,在深入研究 Android 参考资料后,我找到了解决方案。

看起来,当单击子 PreferenceScreen 时,会打开一个包含新 Preference 对象的对话框,而不是新的 Activity 或其他内容。

因此解决方案是检索对话框并使其适合原始 PreferenceFragment 的布局。为此,我使用了 onPreferenceTreeClick 回调方法来检测 PreferenceScreen 是否被点击:

public class SettingsFragment extends PreferenceFragment {

    // onCreate and other stuff...

    @Override
    public boolean onPreferenceTreeClick (PreferenceScreen preferenceScreen, 
                                          Preference preference) {

        // Initiating Dialog's layout when any sub PreferenceScreen clicked
        if(preference.getClass() == PreferenceScreen.class) {
            // Retrieving the opened Dialog
            Dialog dialog = ((PreferenceScreen) preference).getDialog();
            if(dialog == null) return false;

            initDialogLayout(dialog);   // Initiate the dialog's layout
        }
        return true;
    }

    private void initDialogLayout(Dialog dialog) {
        View fragmentView = getView();

        // Get absolute coordinates of the PreferenceFragment
        int fragmentViewLocation [] = new int[2];
        fragmentView.getLocationOnScreen(fragmentViewLocation);

        // Set new dimension and position attributes of the dialog
        WindowManager.LayoutParams wlp = dialog.getWindow().getAttributes();
        wlp.x       = fragmentViewLocation[0]; // 0 for x
        wlp.y       = fragmentViewLocation[1]; // 1 for y
        wlp.width   = fragmentView.getWidth();
        wlp.height  = fragmentView.getHeight();

        dialog.getWindow().setAttributes(wlp);

        // Set flag so that you can still interact with objects outside the dialog
        dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                                    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
    }
}

就是这样,成功了。如果你觉得有更好的方法欢迎评论。