2015-05-11 5 views
15

Ho creato alcune app che supportano più temi, ma ho sempre dovuto riavviare l'app quando l'utente cambia tema, perché setTheme() deve essere chiamato prima dello setContentView().Come cambiare temi (modalità notte) senza riavviare l'attività?

Mi andava bene, fino a quando ho scoperto questa app. Può passare facilmente tra due temi e anche con transizioni/animazioni!

enter image description here

Si prega di darmi alcuni suggerimenti su come questo è stato implementato (e animazioni troppo). Grazie!

+0

è il video è una vera applicazione? – Blackbelt

+0

@Blackbelt Sì, ho registrato il video/gif. L'app si chiama "Zhihu". – user1032613

+0

ehi amico, hai trovato la soluzione per cambiare tema come zhihu? –

risposta

13

@Alexander La risposta di Hanssen ha sostanzialmente risposto a questo ... Non so perché non è stato accettato ... Forse a causa del finish()/startActivity(). Ho votato a favore e ho provato a commentare ma non posso ...

In ogni caso, farei esattamente quello che ha descritto in termini di stili.

<style name="AppThemeLight" parent="Theme.AppCompat.Light"> 
    <!-- Customize your theme here. --> 
    <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item> 
</style> 
<style name="AppThemeDark" parent="Theme.AppCompat"> 
    <!-- Customize your theme here. --> 
    <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item> 
</style> 
<!-- This will set the fade in animation on all your activities by default --> 
<style name="WindowAnimationTransition"> 
    <item name="android:windowEnterAnimation">@android:anim/fade_in</item> 
    <item name="android:windowExitAnimation">@android:anim/fade_out</item> 
</style> 

Ma invece di finitura/iniziare con nuovi intenti:

Intent intent = new Intent(this, <yourclass>.class); 
startActivity(intent); 
finish(); 

lo farei:

@Override 
protected void onCreate(Bundle savedInstanceState) { 

    // MUST do this before super call or setContentView(...) 
    // pick which theme DAY or NIGHT from settings 
    setTheme(someSettings.get(PREFFERED_THEME) ? R.style.AppThemeLight : R.style.AppThemeDark); 

    super.onCreate(savedInstanceState); 
} 

// Somewhere in your activity where the button switches the theme 
btn.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 

     // decide which theme to use DAY or NIGHT and save it 
     someSettings.save(PREFFERED_THEME, isDay()); 

     Activity.this.recreate(); 
    } 
}); 

L'effetto è, come mostrato nel video ...

0

Non c'è niente che ti impedisce di chiamare setTheme() e poi setContentView() di nuovo. Dovrai solo ristrutturare la tua app in modo tale che, se cambi il tema, devi reinizializzare qualsiasi variabile membro che potrebbe contenere riferimenti a oggetti View.

+0

Pensi che sia quello che hanno usato gli sviluppatori dell'app nel video? Dalle animazioni, penso che probabilmente non sono andati in questa direzione. – user1032613

+0

È sicuramente il modo più semplice per farlo. Ho creato app come questa. Finché i tuoi layout non sono troppo complicati, non è un grosso problema.L'unica altra alternativa che posso pensare è scrivere un codice che percorra l'intero albero 'View' e imposta il' tema' su ogni 'vista'. –

4

La transizione/animazione rende il tema senza interruzioni quando si riavvia l'attività, e questo può essere fatto aggiungendo gli elementi "android: windowanimationStyle" ai temi, quindi facendo riferimento a uno stile in cui si specifica come deve animare l'attività quando entra ed esce. Nota che questo rende l'animazione applicabile a tutte le attività con quel tema.

<style name="AppThemeLight" parent="Theme.AppCompat.Light"> 
    <!-- Customize your theme here. --> 
    <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item> 
</style> 
<style name="AppThemeDark" parent="Theme.AppCompat"> 
    <!-- Customize your theme here. --> 
    <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item> 
</style> 
<!-- This will set the fade in animation on all your activities by default --> 
<style name="WindowAnimationTransition"> 
    <item name="android:windowEnterAnimation">@android:anim/fade_in</item> 
    <item name="android:windowExitAnimation">@android:anim/fade_out</item> 
</style> 

Poi, quando si desidera cambiare il tema si potrebbe fare questo quando si fa clic su un pulsante:

AppSettings settings = AppSettings.getInstance(this); 
settings.set(AppSettings.Key.USE_DARK_THEME, 
!settings.getBoolean(AppSettings.Key.USE_DARK_THEME)); 
Intent intent = new Intent(this, <yourclass>.class); 
startActivity(intent); 
finish(); 

Poi nel metodo onCreate, utilizzare il setTheme() per applicare il tema che è attualmente impostato in AppSettings in questo modo:

AppSettings settings = AppSettings.getInstance(this); 
setTheme(settings.getBoolean(AppSettings.Key.USE_DARK_THEME) ? R.style.AppThemeDark : R.style.AppThemeLight); 
super.onCreate(savedInstanceState); 
setContentView(<yourlayouthere>); 

Dai un'occhiata a questo succo di riferimento: https://gist.github.com/alphamu/f2469c28e17b24114fe5

+0

Sebbene ciò possa teoricamente rispondere alla domanda, [sarebbe preferibile] (// meta.stackoverflow.com/q/8259) includere qui le parti essenziali della risposta e fornire il link per riferimento. – manetsus

+0

Per il feedback, ho modificato la mia risposta e incluso le parti essenziali. –