zoontek / react-native-bars

Components to control your app status and navigation bars.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

On Android, the height of the navigation bar does not change after switching the navigation type.

1280103995 opened this issue · comments

commented

Bug summary

In the phone settings, after switching the button navigation to the sliding gesture navigation, the height obtained through NavigationBar.currentHeight is still the previous value.

Reading NavigationBar.tsx can see static currentHeight = NativeModule?.navigationBarHeight;, here a fixed value is returned.

In the StatusBar.js source code:

static currentHeight: ?number =
     Platform.OS ==='android'
       ? NativeStatusBarManagerAndroid.getConstants().HEIGHT
       : null;

In the NativeStatusBarManagerAndroid.js source code:

getConstants(): {|
    +HEIGHT: number,
    +DEFAULT_BACKGROUND_COLOR?: number,
  |} {
    if (constants == null) {
      constants = NativeModule.getConstants();
    }
    return constants;
  },

I am not familiar with flow and typescript, and I cannot push a PR:disappointed:. Can we learn from this approach?

Device: Samsung Galaxy A51 (Android 11)

Library version

1.0.4

Environment info

System:
    OS: macOS 11.5.2
    CPU: (6) x64 Intel(R) Core(TM) i5-8500B CPU @ 3.00GHz
    Memory: 110.27 MB / 8.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 15.4.0 - /usr/local/bin/node
    Yarn: 1.22.17 - /usr/local/bin/yarn
    npm: 7.0.15 - /usr/local/bin/npm
    Watchman: Not Found
  Managers:
    CocoaPods: 1.11.2 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: iOS 14.5, DriverKit 20.4, macOS 11.3, tvOS 14.5, watchOS 7.4
    Android SDK: Not Found
  IDEs:
    Android Studio: 4.2 AI-202.7660.26.42.7486908
    Xcode: 12.5/12E262 - /usr/bin/xcodebuild
  Languages:
    Java: 11.0.8 - /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/javac
    Python: 2.7.16 - /usr/bin/python
  npmPackages:
    @react-native-community/cli: Not Found
    react: Not Found
    react-native: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

Steps to reproduce

  1. In the phone settings, change the button navigation to gesture navigation.
  2. In App.tsx, call NavigationBar.currentHeight.

Reproducible sample code

I just run the example project in the repository.

That's a little be harder than this, since constants are initialized at app startup (the native status bar module suffer from the same issue).

What can be done for now:

commented

That's a little be harder than this, since constants are initialized at app startup (the native status bar module suffer from the same issue).

What can be done for now:

You are right, referring to react native's approach is I was wrong.

I can receive the latest value by doing this, but the component needs to be rendered.

RNBarsModule.java

public void init() {
 ...
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      ViewCompat.setOnApplyWindowInsetsListener(activity.getWindow().getDecorView(), (v, insets) -> {
        int naviHeight;
        if (insets != null) {
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            naviHeight = insets.getInsets(WindowInsets.Type.navigationBars()).bottom;
          } else {
            naviHeight = insets.getSystemWindowInsetBottom();
          }
          sendEvent(PixelUtil.toDIPFromPixel(naviHeight));
        }
        if (insets != null) {
          return ViewCompat.onApplyWindowInsets(v, insets);
        }
        return null;
      });
    }
}
private static void sendEvent(float naviHeight) {
    if (mReactContext == null) return;
    WritableMap event = Arguments.createMap();
    event.putDouble("navigationBarHeight", naviHeight);
    mReactContext
            .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
            .emit("rnBarsNavHeight", event);
  }

NavigationBar.tsx

import * as React from "react";
import { DeviceEventEmitter, Platform } from "react-native";
import { NativeModule } from "./module";
import { NavigationBarProps } from "./types";

const isSupportedPlatform = Platform.OS === "android" && Platform.Version >= 27;

// Listen here
DeviceEventEmitter.addListener('rnBarsNavHeight', data => {
  StatusBar.currentHeight = data.navigationBarHeight;
  console.log('NavigationBar Change: ', StatusBar.currentHeight)
})

export class NavigationBar extends React.Component<StatusBarProps> {
  private static propsStack: NavigationBarProps[] = [];
  private static immediate: NodeJS.Immediate | null = null;
  private static mergedProps: NavigationBarProps | null = null;

 ........
}

I will probably just remove the constants, it's better to use https://github.com/th3rdwave/react-native-safe-area-context which achieve exactly the same job (and more!)

I removed these constants in favor of react-native-safe-area-context: https://github.com/zoontek/react-native-bars/releases/tag/1.1.0