webentwicklung-frage-antwort-db.com.de

Der Voreinstellungs-Unterbildschirm kann nicht geöffnet werden, wenn Sie support.v7.preference verwenden

Ich versuche, Präferenzen mit Unterbildschirmen mit AppCompatActivity und support.v7.preference zu implementieren

Laut den Dokumenten fungiert jedes PreferenceScreen innerhalb eines anderen PreferenceScreen als Unterbildschirm, und das Framework behandelt es, wenn es angeklickt wird . 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>

Dies funktioniert gut, wenn die native Activity, PreferenceFragment ... verwendet wird. Wenn Sie jedoch AppCompatActivity und PreferenceFragmentCompat verwenden, wird durch Klicken auf das Preference-Element nur das Element hervorgehoben, der Unterbildschirm jedoch nicht geöffnet.

Ich konnte nichts finden, wenn ich die Dokumente und den Code las ... muss ich zusätzliche Rückrufe implementieren?


EDIT: Nur zur Vollständigkeit ...

Dies funktioniert und öffnet den Unterbildschirm:

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);
        }
    }
}

Dies funktioniert nicht/öffnet den Unterbildschirm:

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);
        }
    }
}

Edit: 25/01/2016

Nachdem ich einige Tage lang mit support.v7.preference getüftelt hatte, habe ich meine Ergebnisse hier zusammengefasst und gehofft, dass dies anderen helfen kann: HowTo, um support.v7.preference mit AppCompat und möglichen Nachteilen zu verwenden

23
maxdownunder

Es sieht aus wie ein Fehler in PreferenceFragmentCompat oder ein Mangel an Dokumenten. Es hat die Methode onNavigateToScreen, die aufgerufen wird, wenn Sie auf das Element PreferenceScreen klicken.

Die Methode getCallbackFragment () gibt jedoch standardmäßig null zurück, daher müssen Sie sie in Ihrem Fragment überschreiben, um dies zurückzugeben. Außerdem müssen Sie PreferenceFragmentCompat.OnPreferenceStartScreenCallback implementieren.

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;
    }
}

Es führt jedoch zu einem anderen Problem, wenn Sie nicht zu Ihrem ursprünglichen PreferenceScreen zurückkehren können. 

Eine andere Möglichkeit ist, das hier beschriebene Fragment zu ersetzen Wie wechselt man vom Voreinstellungs-Subscreen zum Hauptbildschirm in PreferenceFragmentCompat zurück?

17
LackOfKnowledge

Dies ist ein vollständiges Arbeitsbeispiel. Ich hoffe, dies ist für jemanden hilfreich. Es behandelt das Öffnen des Unterbildschirms für die Einstellungen und das Zurückkehren zum Hauptbildschirm für die Einstellungen.

Ich habe dieses Problem in Android Open Source Issue Tracker -- hier verfolgt

In der offiziellen Dokumentation fehlt die Dokumentation für den Subscreen mit den Ladeeinstellungen -- Informationen zur offiziellen Dokumentation finden Sie hier - -

Der Hauptbildschirm für erweiterte Einstellungen verfügt über 2 Kontrollkästchen und einen deaktivierten Subscreen-Titel (benutzerdefinierte Mustereinstellungen): -

subscreen title disabled

Sobald wir das Kontrollkästchen Benutzerdefiniert aktiviert haben, wird der Titel des Subscreens aktiviert. subscreen title enabled

Beim Klicken auf Benutzerdefinierte Mustereinstellungen wird der Unterbildschirm in einem neuen Bildschirm geöffnet

enter image description here

Hier ist der Beispielcode mit Dokumentation: -

In der Datei 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 sollte die Schnittstelle PreferenceFragmentCompat.OnPreferenceStartScreenCallback Implementieren und dann die Methode überschreiben-- 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;
    }

Für den Haupteinstellungsbildschirm (Fragment): -

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);
    }
}

und zum Schluss für das Laden des Subscreens:

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

Eine äußerst wichtige Sache, an die Sie sich erinnern müssen:

Ihr PreferenceScreen muss enthalten:

Android:key="name_a_unique_key"

Sonst funktioniert es nicht. Ich habe Stunden damit verbracht

2
Richard Mai

Überschreiben PreferenceFragmentCompat.OnPreferenceStartScreenCallback

und das Hinzufügen zu meinem Präferenzfragment rettete meinen Tag

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

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

Meine Vorzugsversion ist

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

Es scheint, dass sich Google letztendlich dafür entscheidet, dies in der neu veröffentlichten AndroidX-Einstellung 1.1.0-alpha zu unterstützen.

Dieses Video von Android Dev Summit behandelt etwas über den Voreinstellungs-Unterbildschirm.

0
Dewey Reed