更改夜间模式后刷新后台堆栈活动

时间:2019-02-28 13:44:22

标签: android android-theme android-night-mode

在更改应用程序的夜间模式后,我已经看到了很多有关重新创建当前活动的问题和答案,但是对于如何刷新后退堆栈活动却一无所知。

说我有后栈 A> B> C 。活动C允许通过调用AppCompatDelegate.setDefaultNightMode()更改夜间模式。调用之后,当前活动(C)可以使用delegate.applyDayNight()recreate()刷新其主题。

但是,当用户导航回B或A时,无论白天还是晚上,活动仍在使用“旧”模式。

我试图在“活动”中添加类似内容:

override fun onResume() {
  super.onResume()
  delegate.applyDayNight()
}

但是它似乎不起作用。

我多次尝试解决此问题:

一个想法是完全像建议的herehere一样重新创建Backstack,但是由于backstack不是静态的,因此对我来说是不可行的。

另一个想法是拥有一个处理夜间模式更改并提供LiveData的类。每个活动都会监听LiveData进行模式更改,然后调用recreate()。但是,我们陷入了无限循环,因为Activity将在开始收听LiveData之后直接重新创建。

我很难相信,我是第一个尝试在更改夜间模式后从后台刷新“活动”的人。我想念什么?

谢谢!

3 个答案:

答案 0 :(得分:1)

快速解答:

    @Override
    protected void onRestart() {
        super.onRestart();

        recreate();
    }

您将以上代码添加到MainActivity中,它将起作用。

答案 1 :(得分:0)

在项目中创建一个静态布尔变量,并在每个活动中检查布尔值是true还是false,然后根据值应用白天和黑夜。

答案 2 :(得分:0)

完全刷新您的后栈可能是过大的选择,可能会增加UX的开销/滞后。正如您提到的,大多数应用程序将无法访问完整的静态后备堆栈。

您实质上是在描述一个更一般的问题:对主题或WindowManager本身的全局更改会影响随后的视图绘制。但是堆栈中“活动”的先前布局可能不会重绘。在这种情况下,对于您来说似乎很奇怪,但是也有很多很好的理由,如果用户再次使用它,就不想在堆栈中重画一个Activity。因此,这不是自动功能。

我可以想到几个选择:

1)编写一个继承自Activity的自定义类,当它再次移到堆栈的最前面时,它将使所有视图无效。例如。在onResume()onRestart()中,致电(如果在Fragment中)

View view = getActivity().findViewById(R.id.viewid);
view.invalidate();

将此自定义活动用于要与当前日/夜模式保持一致的所有活动。

2)使用ActivityLifecycleCallbacks。这有助于将所有逻辑保持在一个地方,并且避免了如上所述的自定义继承的需求。您可以根据需要在此处暂停/恢复活动,从而使视图无效。例如,如果更改主题的是您的应用,则可以包括一个侦听器,并记录为SharedPreference

要使用,请将回调添加到您的Application类:

registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {

    @Override
    public void
    onActivityCreated(Activity activity, Bundle savedInstanceState) {
        //can check type of Activity for custom behaviour, if using inheritance
        if(activity instanceof MainActivity) {
           mMainActivities.put(activity, new MainActivityEntry((MainActivity)activity));
            //...
        }
    }

    @Override
    public void
    onActivityDestroyed(Activity activity) {

    } 

    @Override
    public void
    onActivityPaused(Activity activity) {
    }

    @Override
    public void
    onActivityResumed(Activity activity) {
        if(activity instanceof MainActivity) {
        //...
        }
        //can update Entry properties too
        final MainActivityEntry activityEntry = mMainActivities.get(activity);

        if(activityEntry != null) {
        //record state /perform action
        }
    }

    @Override
    public void
    onActivitySaveInstanceState(Activity activity, Bundle outState) {


    }

    @Override
    public void
    onActivityStarted(Activity activity) {


    }

    @Override
    public void
    onActivityStopped(Activity activity) {
    }
});