flutter_boost icon indicating copy to clipboard operation
flutter_boost copied to clipboard

flutter boost v3.0. 设置了状态栏的样式,退出页面重新进入状态栏设置失效

Open dengzq opened this issue 3 years ago • 16 comments

在测试页面,SystemUiOverlayStyle 设置了状态栏为白色,第一次进入页面样式正常。退出页面之后再重新进入,状态栏样式 不对。

flutter boost分支: master, v3.0-preview.9

可复现代码demo : flutter boost fork工程: https://github.com/dengzq/flutter_boost 分支: master-bug-dengzq 测试代码在 example/ flutter_page.dart

dengzq avatar Aug 06 '21 11:08 dengzq

https://user-images.githubusercontent.com/15603319/128522752-4b9f2040-a138-4faf-bb99-271832f12d7c.mov

dengzq avatar Aug 06 '21 14:08 dengzq

在第二次进入到flutter页面后,由于前一次进入时已经设置过状态栏颜色,即 _latestStyle 并不为空,所以 第二次进入页面时,renderView 在_updateSystemChrome 时并不会真正调用到原生去设置状态栏。

#SystemChrome
static void setSystemUIOverlayStyle(SystemUiOverlayStyle style) {
    assert(style != null);
    if (_pendingStyle != null) {
      // The microtask has already been queued; just update the pending value.
      _pendingStyle = style;
      return;
    }
    // 此时 _latestStyle 在第二次进入页面时与要设置的状态栏样式一致,此处 return
    if (style == _latestStyle) {
      return;
    }
    _pendingStyle = style;
    scheduleMicrotask(() {
      assert(_pendingStyle != null);
      if (_pendingStyle != _latestStyle) {
        SystemChannels.platform.invokeMethod<void>(
          'SystemChrome.setSystemUIOverlayStyle',
          _pendingStyle!._toMap(),
        );
        _latestStyle = _pendingStyle;
      }
      _pendingStyle = null;
    });
  }

由于前面 SystemChrome 执行设置样式时 return , 也就不会真正调用到原生的 PlatformPlugin 了。

#Android#PlatformPlugin
@Override
public void setSystemUiOverlayStyle(
            @NonNull PlatformChannel.SystemChromeStyle systemUiOverlayStyle) {
          setSystemChromeSystemUIOverlayStyle(systemUiOverlayStyle);
}

安卓要处理状态栏问题的,目前想到的方法是,可以暂时在原生侧去处理,比如拷贝setSystemChromeSystemUIOverlayStyle 代码进行状态栏的设置。

dengzq avatar Aug 24 '21 06:08 dengzq

在测试页面,SystemUiOverlayStyle 设置了状态栏为白色,第一次进入页面样式正常。退出页面之后再重新进入,状态栏样式 不对。

flutter boost分支: master, v3.0-preview.9

可复现代码demo : flutter boost fork工程: https://github.com/dengzq/flutter_boost 分支: master-bug-dengzq 测试代码在 example/ flutter_page.dart

#1338 请问这个问题怎么处理的

Qson8 avatar Aug 31 '21 02:08 Qson8

这个问题我也遇到了 目前是通过页面销毁的时候 还原设置 让下一次设置生效 目前最好的方案就是交给原生侧处理

zhixinpeng avatar Sep 06 '21 12:09 zhixinpeng

在com.idlefish.flutterboost/containers/FlutterBoostActivity.java里添加如下代码,并取消flutter模块和native模块对状态栏的设置 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public void onPostResume() { super.onPostResume(); getWindow().setStatusBarColor(0); }

Alrey-xxl avatar Sep 27 '21 07:09 Alrey-xxl

在第二次进入到flutter页面后,由于前一次进入时已经设置过状态栏颜色,即 _latestStyle 并不为空,所以 第二次进入页面时,renderView 在_updateSystemChrome 时并不会真正调用到原生去设置状态栏。

#SystemChrome
static void setSystemUIOverlayStyle(SystemUiOverlayStyle style) {
    assert(style != null);
    if (_pendingStyle != null) {
      // The microtask has already been queued; just update the pending value.
      _pendingStyle = style;
      return;
    }
    // 此时 _latestStyle 在第二次进入页面时与要设置的状态栏样式一致,此处 return
    if (style == _latestStyle) {
      return;
    }
    _pendingStyle = style;
    scheduleMicrotask(() {
      assert(_pendingStyle != null);
      if (_pendingStyle != _latestStyle) {
        SystemChannels.platform.invokeMethod<void>(
          'SystemChrome.setSystemUIOverlayStyle',
          _pendingStyle!._toMap(),
        );
        _latestStyle = _pendingStyle;
      }
      _pendingStyle = null;
    });
  }

由于前面 SystemChrome 执行设置样式时 return , 也就不会真正调用到原生的 PlatformPlugin 了。

#Android#PlatformPlugin
@Override
public void setSystemUiOverlayStyle(
            @NonNull PlatformChannel.SystemChromeStyle systemUiOverlayStyle) {
          setSystemChromeSystemUIOverlayStyle(systemUiOverlayStyle);
}

安卓要处理状态栏问题的,目前想到的方法是,可以暂时在原生侧去处理,比如拷贝setSystemChromeSystemUIOverlayStyle 代码进行状态栏的设置。

这种场景确实有点麻烦。后退后再次进来时,Activity已经是新的了,PlatformPlugin也新创建了,Dart上次设置给Native的style也不方便恢复。

0xZOne avatar Oct 19 '21 11:10 0xZOne

这个问题我也遇到了 目前是通过页面销毁的时候 还原设置 让下一次设置生效 目前最好的方案就是交给原生侧处理

嗯,Flutter页面销毁时进行重置,这是一种解法。

0xZOne avatar Oct 19 '21 11:10 0xZOne

这个问题 我也遇到了, flutter设置了状态栏样式,第一次进去没问题。退出去 然后重新进去 状态栏设置失效

重现的代码 https://github.com/liuyicheng3/flutter_boost/tree/dev-replay-status-bar 路径:第一个页面进去 =》 “open flutter page”

liuyicheng3 avatar Dec 26 '21 09:12 liuyicheng3

我在自己的項目中用了此方法,到目前为止,没有再出现过这种情况,在FlutterBoostActivity中添加如下代码: @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public void onPostResume() { super.onPostResume(); getWindow().setStatusBarColor(0); }

Alrey-xxl avatar Dec 27 '21 05:12 Alrey-xxl

这个问题我也遇到了 目前是通过页面销毁的时候 还原设置 让下一次设置生效 目前最好的方案就是交给原生侧处理

嗯,Flutter页面销毁时进行重置,这是一种解法。

我遇到的情况是状态栏为白色,第二次进入时,文字的颜色会从黑变成白,请问这个问题有解决方案吗?

yoni1988 avatar Aug 26 '22 00:08 yoni1988

可以让每次设置的style都不一样,比如状态栏一般用的透明的,可以把其他通道的颜色,改变下。让官方暴露个方法,能把 style 重置成null 就好了

zmtzawqlp avatar Sep 27 '22 09:09 zmtzawqlp

可以让每次设置的style都不一样,比如状态栏一般用的透明的,可以把其他通道的颜色,改变下。让官方暴露个方法,能把 style 重置成null 就好了

提个PR给官方~~

0xZOne avatar Sep 27 '22 09:09 0xZOne

可以让每次设置的style都不一样,比如状态栏一般用的透明的,可以把其他通道的颜色,改变下。让官方暴露个方法,能把 style 重置成null 就好了

提个PR给官方~~

p5 警告

zmtzawqlp avatar Sep 28 '22 01:09 zmtzawqlp

我发现 在 flutterA =》原生=》flutterB,然后从 flutterB 退到原生的时候,会提前触发 SystemChrome.setSystemUIOverlayStyle,会把 flutterA 的状态栏信息提前设置,导致从原生回到 flutterA 状态栏又没有设置。

最后只能在 onPageShow 的时候执行下面的代码,直接干不要怂。

  static void setSystemUIOverlayStyle() {
    final SystemUiOverlayStyle? style = SystemChrome.latestStyle;
    if (style == null) {
      return;
    }
    scheduleMicrotask(() {
      SystemChannels.platform.invokeMethod<void>(
        'SystemChrome.setSystemUIOverlayStyle',
        <String, dynamic>{
          'systemNavigationBarColor': style.systemNavigationBarColor?.value,
          'systemNavigationBarDividerColor':
              style.systemNavigationBarDividerColor?.value,
          'systemStatusBarContrastEnforced':
              style.systemStatusBarContrastEnforced,
          'statusBarColor': style.statusBarColor?.value,
          'statusBarBrightness': style.statusBarBrightness?.toString(),
          'statusBarIconBrightness': style.statusBarIconBrightness?.toString(),
          'systemNavigationBarIconBrightness':
              style.systemNavigationBarIconBrightness?.toString(),
          'systemNavigationBarContrastEnforced':
              style.systemNavigationBarContrastEnforced,
        },
      );
    });
  }

zmtzawqlp avatar Feb 16 '23 08:02 zmtzawqlp

这个问题我也遇到了 目前是通过页面销毁的时候 还原设置 让下一次设置生效 目前最好的方案就是交给原生侧处理

请问你这边具体是怎么处理的呢?

jasondevelopment avatar Apr 10 '23 03:04 jasondevelopment

我们这边的处理方案是使用Fragment作为flutter容器,在Activity的onCreate中添加Android原生部分沉浸式状态栏方法:

 if (activity != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Window window = activity.getWindow();
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                    | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);

            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(Color.TRANSPARENT);

            InitStatusBarColor(activity, isDark);
        }

缺点是不能在flutter中控制是否展示沉浸式样式

booqin avatar Apr 20 '23 04:04 booqin