2016-01-10 11 views
17

Sto cercando di attuare preferenze con schermi secondari utilizzando AppCompatActivity e support.v7.preferencePreferenza schermo secondario non si apre quando si utilizza support.v7.preference

Secondo la documentazione, ogni PREFERENCE entro ulteriori funzioni come PREFERENCE una sottoschermata e il framework gestirà la visualizzazione quando viene cliccato. 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> 

Questo funziona bene con attività nativa, PreferenceFragment ... ma utilizzando AppCompatActivity e PreferenceFragmentCompat, cliccando l'elemento di preferenza solo mette in evidenza, ma non apre la schermata secondaria.

Non riesco a trovare nulla su questa lettura dei documenti e del codice ... devo implementare eventuali richiami aggiuntivi?


EDIT: solo per completezza ...

Questo funziona e si apre lo schermo secondario:

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

Questo non funziona/aprire lo schermo secondario:

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

Dopo armeggiare con support.v7.preference per qualche giorno, ho riassunto i miei risultati qui, nella speranza che possa aiutare gli altri: HowTo use support.v7.preference with AppCompat and potential drawbacks

risposta

12

Sembra un bug in PreferenceFragmentCompat o insufficienza di documenti. Ha un metodo onNavigateToScreen che viene chiamato quando si fa clic sulla voce PreferenceScreen.

Ma il metodo getCallbackFragment() restituisce null per impostazione predefinita, quindi è necessario sovrascriverlo nel frammento per restituirlo. Inoltre è necessario implementare 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; 
    } 
} 

Ma porta a un altro problema quando non è possibile ottenere di nuovo al vostro PREFERENCE iniziale,

Un altro modo è quello di sostituire frammento che è descritta qui How to move back from Preferences subscreen to main screen in PreferenceFragmentCompat?

+0

Grazie per il tuo aiuto! Nel frattempo ho lavorato su questo argomento e ho pubblicato un riepilogo della mia esperienza relativa a support.v7.preference qui: http://stackoverflow.com/questions/34983932/howto-use-support-v7-preference-with-appcompat-and- potenziali svantaggi/34983933 # 34983933 Forse dai un'occhiata e vedi se hai qualcosa da aggiungere ... – maxdownunder

10

Questo è completo esempio di lavoro, Spero che questo possa essere d'aiuto a qualcuno. Copre l'apertura della schermata di preferenza e tornare alla schermata delle Impostazioni principali.

Ho seguito questo problema in Android problema open source Tracker - here

La documentazione ufficiale non è presente la documentazione per il carico preferenza subscreen- Refer here for official documentation- -

Le principali impostazioni avanzate schermo come 2 caselle di controllo e un disabile titolo sottoschermo (impostazioni del tipo personalizzato): -

subscreen title disabled

Una volta che controlliamo la casella di controllo personalizzato, il il titolo sottoscreen è abilitato. subscreen title enabled

Al clic di impostazioni personalizzate del modello, il sottoschermo apre in una nuova schermata

enter image description here

Ecco il codice di esempio con la documentazione: -

In res/xml/preferences File .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 deve implementare l'interfaccia PreferenceFragmentCompat.OnPreferenceStartScreenCallback e quindi sostituire l'method-- 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; 
    } 

Per la schermata Impostazioni principale (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); 
    } 
} 

e infine per il caricamento della sub:

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

Bella soluzione –

2

Una cosa estremamente importante che devi ricordare:

vostri PREFERENCE devono contenere:

android:key="name_a_unique_key" 

In caso contrario, non funzionerà. Ho passato ore con THI

1

Overriding PreferenceFragmentCompat.OnPreferenceStartScreenCallback

e aggiungendo il seguente alla mia preferenza frammento salvato la mia giornata

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

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

La mia versione preferenza è

compile 'com.android.support:preference-v7:25.0.0'