2015-01-30 22 views
18

Ho lottato con il tentativo di ottenere il mio PreferenceFragment per avere lo stesso tema e lo stesso stile (tramite AppCompat) come il resto della mia applicazione. Il PreferenceFragment che sto usando per gestire tutte le mie impostazioni dell'applicazione è mostrata di seguito:Applicazione del tema AppCompat alle preferenze individuali in un PreferenceFragment

enter image description here

Come si può vedere dalla schermata qui sopra, sono stato in grado di personalizzare il PreferenceFragment utilizzando colorAccent, colorPrimary, e un pochi altri attributi. Il mio tema per la PreferenceFragment è la seguente:

<style 
    name="settingsTheme" 
    parent="Theme.AppCompat.Light.DarkActionBar"> 
    <item name="colorPrimary">@color/blue_grey_500</item> 
    <item name="colorAccent">@color/blue_grey_500</item> 
    <item name="android:textColor">@color/black_text_alt</item> 
    <item name="android:textColorSecondary">@color/black_secondary_text</item> 
</style> 

Tuttavia, nonostante i miei sforzi, non sono in grado di applicare i temi ai singoli elementi nel mio PreferenceFragment, come ad esempio ListPreference e EditTextPreference; tutte le preferenze conservano ancora il tema AppCompat di serie:

enter image description here

Ho trovato un vecchio post due anni che discute il problema, anche se con nessuna vera soluzione: How to apply theme to <PreferenceScreen> elements of a <PreferenceCategory>

Mi chiedo se qualcuno è stato in grado di applicare con successo temi alle preferenze da quando è stato rilasciato AppComat V21. In caso contrario, esistono soluzioni alternative valide che possono essere utilizzate per applicare temi personalizzati alle singole preferenze?

risposta

9

UPDATE: ho fatto una libreria per combattere il problema (usa AppCompat r22): https://github.com/consp1racy/android-support-preference


Il ListPreference estende DialogPreference che utilizza questo pezzo di codice per creare la finestra di dialogo:

mBuilder = new AlertDialog.Builder(context) 
    .setTitle(mDialogTitle) 
    .setIcon(mDialogIcon) 
    .setPositiveButton(mPositiveButtonText, this) 
    .setNegativeButton(mNegativeButtonText, this); 

Come si può vedere il costruttore AlertDialog.Builder non viene fornito con il secondo parametro opzionale int theme. Ciò significa che la finestra di dialogo sarà a tema indipendentemente dal tema della tua attività nell'attributo android:alertDialogTheme.

Ora è necessario creare un tema personalizzato per la tua finestra di dialogo che deriva da Theme.AppCompat.Dialog in questo modo:

<style name="Theme.YourApp.Dialog.Alert" parent="Theme.AppCompat.Light.Dialog"> 
    <item name="android:windowBackground">@android:color/transparent</item> 
    <item name="android:windowContentOverlay">@null</item> 
    <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item> 
    <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item> 
    <item name="colorAccent">@color/accent_yourapp</item> 
    <item name="colorPrimary">@color/primary_yourapp</item> 
    <item name="colorPrimaryDark">@color/primary_dark_yourapp</item> 
</style> 

Problema 1: La soluzione di cui sopra non funzionerà per RingtonePreference perché non si estende ListPreference ma le chiamate un intento di scelta della suoneria, quindi è sempre a tema secondo il sistema. Dai un'occhiata a questa risposta: RingtonePreference Theme Quindi possiamo contrassegnare questo come risolto.

Problema 2: Le finestre di dialogo AppCompat mancano di titolo. E finora non ho trovato un modo per risolvere questo problema. Vero che non sto guardando abbastanza bene. Ignoriamo l'assenza del titolo come un problema minore.

Problema 3: Il pulsante drawable radiofonici non sono mutati in modo la grafica non sono coerenti tra stato passivo e attivo (colorato) - tutti sono colorati (non solo quello che si ri premendo!) O tutti sono grigi.Ora, questo è davvero fastidioso

problemi 2 & 3 mi ha costretto a prendere un'altra strada - la mia finestra tema appare così su API 14+

<style name="Theme.MyApp.Dialog.Alert" parent="android:Theme.DeviceDefault.Light.Dialog.MinWidth"> 
    <item name="android:windowBackground">@android:color/transparent</item> 
    <item name="android:windowContentOverlay">@null</item> 
</style> 

e come questo su API 21+

<style name="Theme.YourApp.Dialog.Alert" parent="android:Theme.DeviceDefault.Light.Dialog.MinWidth"> 
    <item name="android:colorPrimary">@color/primary_yourapp</item> 
    <item name="android:colorPrimaryDark">@color/primary_dark_yourapp</item> 
    <item name="android:colorAccent">@color/accent_yourapp</item> 
</style> 

Questi valori sono stati acquisiti sperimentalmente eseguendo la scansione attraverso i file sorgente della piattaforma e ben testato.

Il punto è che l'unica soluzione affidabile sembra utilizzare il tema di dialogo predefinito del dispositivo. L'unica scelta prima di Lollipop è una variante chiara o scura. Su Lollipop questo funzionerà come previsto e richiesto.

EDIT: Dal appcompat-v7-r21.1.0 è possibile utilizzare AppCompatDialog che è materiale la variante a tema di natale AlertDialog.

È possibile utilizzare fornito AlertDialog.Builder (da non confondere con la controparte nativa) per la creazione delle sue istanze.

+0

Grazie. Questo è quello di cui avevo bisogno. – Willis

+0

Su AppCompat v22.1 è possibile utilizzare android.support.v7.app.AlertDialog –

+2

Sì, desidero che lo avessi 6 mesi fa: D –

1

Si consiglia di verificare this Gist su come i diversi componenti utilizzano gli attributi del colore del tema. Potrebbe essere necessario aggiungere i seguenti attributi per il vostro tema per ottenere l'effetto desiderato:

<item name="colorControlNormal">@color/x_color</item> 
<item name="colorControlActivated">@color/y_color</item> 
<item name="colorControlHighlight">@color/z_color</item> 
+0

Questo è bello sapere. Sfortunatamente, questi attributi non sembrano influenzare le varie preferenze ('EditTextPreference',' ListPreference', ecc.), Solo la 'PreferenceScreen' di root. – Willis

3

DialogPreference utilizza android.app.AlertDialog.Builder direttamente in modo che sarebbe stato impossibile per passare la finestra di dialogo visualizzata alla progettazione materiale uno per tutti i livelli di API (che richiede l'uso di android.support.v7.widget.AlertDialog.Builder).

Credo che l'unica opzione per ora sia estendere e ignorare la logica di creazione della finestra di dialogo in DialogPreference o nelle sue sottoclassi (e utilizzare reflection per aggirare gli accessor privati, se necessario). Dai un'occhiata a questo reddit thread e un esempio AppCompatListPreference creato dall'autore di quella discussione.

2

Prendendo spunto dalle risposte già date ho impostato nel manifesto un tema personalizzato per l'attività Impostazioni perché è necessario rimuovere lo sfondo del bordo intorno alla finestra di dialogo che appare, utilizzando uno sfondo trasparente questo solo per API < 21:

AndroidManifest.xml

<application 
    android:name=".MyApplication" 
    ... 
    android:theme="@style/AppTheme"> 
    ... 
    <activity 
     android:name=".ui.SettingsActivity" 
     ... 
     android:theme="@style/AppTheme.Settings"> 
    </activity> 
</application> 

valori/style.xml

.210

infine per VALORI v21 /style.xml finestra normale, se non mettere questo in finestre di dialogo V21 sarà trasparente.

<style name="AppTheme.Settings" parent="AppTheme.Base"> 
    <item name="android:alertDialogTheme">@style/AppTheme.AlertDialog</item> 
</style> 

In realtà io ho il problema di impostare i colori direttamente dal parco tematico attributi:? Android: colorAccent invece del mio colore fisso @ colore/accent_light.

Problemi correlati