web-dev-qa-db-ja.com

support.v7.preferenceを使用すると、設定サブ画面が開かない

AppCompatActivityとsupport.v7.preferenceを使用して、サブ画面で設定を実装しようとしています

ドキュメントによると、別のPreferenceScreen内のすべてのPreferenceScreenはサブ画面として機能し、フレームワークはクリックされたときにそれを表示します。 http://developer.Android.com/guide/topics/ui/settings.html#Subscreens

<PreferenceScreen  xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <!-- opens a subscreen of settings -->
    <PreferenceScreen
        Android:key="button_voicemail_category_key"
        Android:title="@string/voicemail"
        Android:persistent="false">
        <ListPreference
            Android:key="button_voicemail_provider_key"
            Android:title="@string/voicemail_provider" ... />
        <!-- opens another nested subscreen -->
        <PreferenceScreen
            Android:key="button_voicemail_setting_key"
            Android:title="@string/voicemail_settings"
            Android:persistent="false">
            ...
        </PreferenceScreen>
        <RingtonePreference
            Android:key="button_voicemail_ringtone_key"
            Android:title="@string/voicemail_ringtone_title"
            Android:ringtoneType="notification" ... />
        ...
    </PreferenceScreen>
    ...
</PreferenceScreen>

これは、ネイティブのActivity、PreferenceFragment ...を使用して正常に機能しますが、AppCompatActivityおよびPreferenceFragmentCompatを使用して、Preference要素をクリックすると強調表示されるだけで、サブ画面は開きません。

私はこれをドキュメントとコードを読んで何も見つけることができませんでした...追加のコールバックを実装する必要がありますか?


編集:完全を期すために...

これが機能し、サブ画面が開きます。

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState == null) {
            getFragmentManager().beginTransaction()
                    .replace(Android.R.id.content, new DemoPreferenceFragment())
                    .commit();
        }
    }

    static public class DemoPreferenceFragment extends PreferenceFragment {

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.preferences);
        }
    }
}

これは機能しません/サブ画面を開きます:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .replace(Android.R.id.content, new DemoPreferenceFragment())
                    .commit();
        }
    }

    static public class DemoPreferenceFragment extends PreferenceFragmentCompat {

        @Override
        public void onCreatePreferences(Bundle bundle, String s) {
            addPreferencesFromResource(R.xml.preferences);
        }
    }
}

編集:25/01/2016

support.v7.preferenceを数日間いじった後、私はここで私の発見を要約しました、それが他の人に役立つことを願っています: HowToのsupport.v7 AppCompatの設定と潜在的な欠点

25
maxdownunder

PreferenceFragmentCompatのバグまたはドキュメントの不足のようです。 PreferenceScreen項目をクリックすると呼び出されるonNavigateToScreenメソッドがあります。

ただし、メソッドgetCallbackFragment()はデフォルトでnullを返すため、これを返すにはフラグメントでオーバーライドする必要があります。また、PreferenceFragmentCompat.OnPreferenceStartScreenCallbackを実装する必要があります。

public class SettingsFragment extends PreferenceFragmentCompat implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback {

    public static SettingsFragment newInstance() {
        return new SettingsFragment();
    }

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        addPreferencesFromResource(R.xml.news_settings);
    }

    @Override
    public Fragment getCallbackFragment() {
        return this;
    }

    @Override
    public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat, PreferenceScreen preferenceScreen) {
        preferenceFragmentCompat.setPreferenceScreen(preferenceScreen);
        return true;
    }
}

ただし、最初のPreferenceScreenに戻れない場合は、別の問題が発生します。

別の方法は、ここで説明されているフラグメントを置き換えることです PreferenceFragmentCompatのPreferencesサブ画面からメイン画面に戻る方法

18
LackOfKnowledge

これは完全に機能する例ですが、これが誰かに役立つことを願っています。設定サブ画面を開いて、メイン設定画面に戻る方法について説明します。

私はAndroidオープンソースの問題トラッカー- ここでこの問題を追跡しました

公式ドキュメントには、設定サブ画面の読み込みに関するドキュメントがありません— 公式ドキュメントについては、こちらを参照してください- -

メインの詳細設定画面には2つのチェックボックスがあり、サブ画面のタイトルが無効になっています(カスタムパターン設定):-

subscreen title disabled

カスタムチェックボックスをチェックすると、従属画面のタイトルが有効になります。 subscreen title enabled

カスタムパターン設定をクリックすると、サブ画面が新しい画面で開きます

enter image description here

これがドキュメントのサンプルコードです:-

Res/xml/preferences.xmlファイル:-

    <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:summary="Trying intro text">
    <PreferenceCategory Android:title="Settings">
        <CheckBoxPreference
            Android:defaultValue="true"
            Android:key="defaultPress"
            Android:title="Default settings" />
        <CheckBoxPreference
            Android:defaultValue="false"
            Android:key="customKey"
            Android:title="Custom" />
        <PreferenceScreen
            Android:key="customPrefKey"
            Android:title="Custom Pattern Settings">
            <PreferenceCategory
                Android:key="customSettingsKey"
                Android:title="Custom Settings">
                <ListPreference
                    Android:defaultValue="4"
                    Android:entries="@array/initialClickArray"
                    Android:entryValues="@array/initialClickValues"
                    Android:key="initialClicks"
                    Android:summary="initialClicksSummary"
                    Android:title="No. Of Clicks" />
                <ListPreference
                    Android:defaultValue="5"
                    Android:entries="@array/initialTimeArray"
                    Android:entryValues="@array/initialTimeValues"
                    Android:key="initialTimeKey"
                    Android:summary="Time to complete clicks"
                    Android:title="Time to complete" />
            </PreferenceCategory>
        </PreferenceScreen>
    </PreferenceCategory>
</PreferenceScreen>

MainActivity.Javaは、インターフェイスPreferenceFragmentCompat.OnPreferenceStartScreenCallbackを実装してから、メソッドをオーバーライドする必要があります-onPreferenceStartScreen

public class MainActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback {

    private static final String TAG = MainActivity.class.getName();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment fragment = null;
        if (savedInstanceState == null) {
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragment = new AdvancedSettingsFragment().newInstance("Advanced Setting");
            fragmentTransaction.add(R.id.fragment_container, fragment);
            fragmentTransaction.commit();
        }
    }

    @Override
        public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat,
                                           PreferenceScreen preferenceScreen) {
        Log.d(TAG, "callback called to attach the preference sub screen");
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        AdvancedSettingsSubScreenFragment fragment = AdvancedSettingsSubScreenFragment.newInstance("Advanced Settings Subscreen");
        Bundle args = new Bundle();
        //Defining the sub screen as new root for the  subscreen
        args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.getKey());
        fragment.setArguments(args);
        ft.replace(R.id.fragment_container, fragment, preferenceScreen.getKey());
        ft.addToBackStack(null);
        ft.commit();
        return true;
    }

メイン設定画面(フラグメント)の場合:-

public class AdvancedSettingsFragment extends PreferenceFragmentCompat {
    private static final String TAG = AdvancedSettingsFragment.class.getName();
    public static final String PAGE_ID = "page_id";

    public static AdvancedSettingsFragment newInstance(String pageId) {
        AdvancedSettingsFragment f = new AdvancedSettingsFragment();
        Bundle args = new Bundle();
        args.putString(PAGE_ID, pageId);
        f.setArguments(args);
        return (f);
    }

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.preferences);
        final CheckBoxPreference customPreference = (CheckBoxPreference) findPreference("customKey");
        final Preference customSettings = (Preference) findPreference("customPrefKey");
        // First time loading the preference screen, we check the saved settings and enable/disable the custom settings, based on the custom check box
        //get the customSettings value from shared preferences
        if (getCustomSettings(getActivity())) {
            customPreference.setChecked(true);
            customSettings.setEnabled(true);
        } else {
            customPreference.setChecked(false);
            customSettings.setEnabled(false);
        }
        customPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object selectedValue) {
                Log.d(TAG, "Inside on preference change of custom checkbox selection " + selectedValue.getClass());
                if ((Boolean) selectedValue) {
                    customSettings.setEnabled(true);
                }else{
                    customSettings.setEnabled(false);
                }
                return true;
            }
        });
    }
    private boolean getCustomSettings(Context context) {
        return PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean("customKey", false);
    }
}

そして最後に、従属画面のロード:

public class AdvancedSettingsSubScreenFragment extends PreferenceFragmentCompat {
    private static final String TAG = AdvancedSettingsSubScreenFragment.class.getName();
    public static final String PAGE_ID = "page_id";

    public static AdvancedSettingsSubScreenFragment newInstance(String pageId) {
        AdvancedSettingsSubScreenFragment f = new AdvancedSettingsSubScreenFragment();
        Bundle args = new Bundle();
        args.putString(PAGE_ID, pageId);
        f.setArguments(args);
        return (f);
    }

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        // rootKey is the name of preference sub screen key name , here--customPrefKey
        setPreferencesFromResource(R.xml.preferences, rootKey);
        Log.d(TAG, "onCreatePreferences of the sub screen " + rootKey);
    }
}
14
Nicks

覚えておく必要のある非常に重要なことの1つ:

PreferenceScreenには以下が含まれている必要があります。

Android:key="name_a_unique_key"

それ以外の場合は機能しません。私は何時間も過ごしました

2
mvmanh

オーバーライドPreferenceFragmentCompat.OnPreferenceStartScreenCallback

そして、私の好みのフラグメントに以下を追加すると、私の日が救われました

@Override
public Fragment getCallbackFragment() {
    return this;
}

@Override
public boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref) {
    caller.setPreferenceScreen(pref);
    return true;
}

私の好みのバージョンは

compile 'com.Android.support:preference-v7:25.0.0'
0
Youness

Googleはついに、新しくリリースされたAndroidX設定1.1.0-alphaでこれをサポートすることを最終的に決定したようです。

Android Dev Summitのこのビデオでは、設定サブ画面について説明しています

0
Dewey Reed