web-dev-qa-db-ja.com

アクティビティを再開せずにテーマを切り替える方法(夜間モード)

複数のテーマをサポートするアプリをいくつか作成しましたが、setTheme()setContentView()の前に呼び出す必要があるため、ユーザーがテーマを切り替えるときに常にアプリを再起動する必要がありました。

このアプリが見つかるまで大丈夫でした。 2つのテーマをシームレスに切り替えることができ、トランジション/アニメーションも使用できます。

enter image description here

これがどのように実装されたか(およびアニメーションも)のヒントを教えてください。ありがとう!

38
user1032613

@Alexander Hanssenの答えは基本的にこれに答えています...なぜそれが受け入れられなかったのかわからない...多分finish()/ startActivity()のせいです。私はそれに投票し、コメントしようとしましたが、できません...

とにかく、私は彼がスタイルの点で説明したことを正確に行います。

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

しかし、新しい目的で終了/開始する代わりに:

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

私はします:

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

効果はビデオに示されているとおりです...

46
GKA

トランジション/アニメーションは、アクティビティを再開したときにテーマをシームレスに変更します。これを行うには、テーマに「Android:windowanimationStyle」というアイテムを追加し、アクティビティが開始したときのアニメーションの方法を指定するスタイルを参照します。終了します。これにより、アニメーションはそのテーマのすべてのアクティビティに適用されます。

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

次に、テーマを変更する場合は、ボタンをクリックすると次のようになります。

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

次に、onCreateメソッドでsetTheme()を使用して、次のようにAppSettingsで現在設定されているテーマを適用します。

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

参考のためにこのGistを確認してください: https://Gist.github.com/alphamu/f2469c28e17b24114fe5

14

setTheme()を呼び出してからsetContentView()を再度呼び出すことを妨げるものはありません。アプリを少し再構成するだけで、テーマを変更した場合に、Viewオブジェクトへの参照を保持している可能性のあるメンバー変数を再初期化する必要があります。

1
David Wasser