2015-05-11 10 views
15

Zrobiłem kilka aplikacji, które obsługują wiele motywów, ale zawsze musiałem ponownie uruchomić aplikację, gdy użytkownik przełącza motyw, ponieważ setTheme() musi być wywołany przed setContentView().Jak zmienić motywy (tryb nocny) bez ponownego uruchamiania aktywności?

Byłem w porządku z tym, dopóki nie znalazłem tej aplikacji. Może płynnie przełączać się między dwoma tematami, a także z przejściami/animacjami!

enter image description here

proszę dać mi kilka wskazówek, jak to zostało zrealizowane (i animacje zbyt). Dzięki!

+0

jest wideo to prawdziwa aplikacja? – Blackbelt

+0

@ Blackbelt Tak, nagrałem wideo/gif. Aplikacja nazywa się "Zhihu". – user1032613

+0

Hej przyjacielu, czy znalazłeś solutin do zmiany tematu jak zhihu? –

Odpowiedz

13

@Alexander Odpowiedź Hanssena w zasadzie odpowiedział na to ... Nie wiem, dlaczego nie został przyjęty ... Może ze względu na wykończenie()/startActivity(). Głosowałem za tym i próbowałem komentować, ale nie mogę ...

W każdym razie zrobiłbym dokładnie to, co opisał pod względem stylów.

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

Ale zamiast wykończenia/start z nowym zamiarem:

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

chciałbym zrobić:

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

Efekt jest taki jak pokazano w filmie ...

0

Nic nie stoi na przeszkodzie, aby ponownie zadzwonić pod numer setTheme(), a następnie setContentView(). Musisz tylko trochę zmienić strukturę swojej aplikacji, aby zmienić motyw, musisz ponownie zainicjować dowolne zmienne członkowskie, które zawierają odniesienia do obiektów View.

+0

Czy sądzisz, że to właśnie wykorzystali twórcy aplikacji w filmie? Z animacji czuję, że prawdopodobnie nie podążali w tym kierunku. – user1032613

+0

To z pewnością najłatwiejszy sposób na zrobienie tego. Zbudowałem takie aplikacje. Dopóki twoje układy nie są zbyt skomplikowane, nie jest to wielka sprawa.Jedyną alternatywą, o której myślę, jest napisanie kodu przechodzącego przez całe drzewo 'Widok' i ustawienie' Theme' na każdym "widoku". –

4

Przejście/animacja powoduje, że motyw zmienia się płynnie po ponownym uruchomieniu działania, a można tego dokonać dodając elementy "android: windowanimationStyle" do motywów, a następnie odwołując się do stylu, w którym określa się sposób animacji działania. kiedy wchodzi i wychodzi. Należy pamiętać, że powoduje to zastosowanie animacji we wszystkich działaniach związanych z tym tematem.

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

Potem, gdy chcesz zmienić motyw, który może to zrobić po kliknięciu przycisku:

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

Następnie w metodzie onCreate, korzystania z setTheme() aby zastosować motyw, który jest aktualnie ustawiony w AppSettings tak:

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

Sprawdź to GIST dla odniesienia: https://gist.github.com/alphamu/f2469c28e17b24114fe5

+0

Chociaż może to teoretycznie odpowiedzieć na pytanie, [byłoby lepiej] (// meta.stackoverflow.com/q/8259), aby uwzględnić istotne części odpowiedzi tutaj, i podać link dla odniesienia. – manetsus

+0

Thats za opinię, ja zredagowałem moją odpowiedź i włączyłem zasadnicze części. –

Powiązane problemy