diff --git a/android/src/main/java/com/swmansion/reanimated/keyboard/Keyboard.java b/android/src/main/java/com/swmansion/reanimated/keyboard/Keyboard.java index 0f8ae78071e..d71bd5f0725 100644 --- a/android/src/main/java/com/swmansion/reanimated/keyboard/Keyboard.java +++ b/android/src/main/java/com/swmansion/reanimated/keyboard/Keyboard.java @@ -1,7 +1,5 @@ package com.swmansion.reanimated.keyboard; -import android.view.KeyCharacterMap; -import android.view.KeyEvent; import androidx.core.view.WindowInsetsCompat; import com.facebook.react.uimanager.PixelUtil; @@ -23,9 +21,7 @@ public int getHeight() { public void updateHeight(WindowInsetsCompat insets) { int contentBottomInset = insets.getInsets(CONTENT_TYPE_MASK).bottom; int systemBarBottomInset = insets.getInsets(SYSTEM_BAR_TYPE_MASK).bottom; - boolean hasNavigationBar = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME); - int keyboardHeightDip = - hasNavigationBar ? contentBottomInset - systemBarBottomInset : contentBottomInset; + int keyboardHeightDip = contentBottomInset - systemBarBottomInset; int keyboardHeight = (int) PixelUtil.toDIPFromPixel(Math.max(0, keyboardHeightDip)); if (keyboardHeight == 0 && mState == KeyboardState.OPEN) { /* @@ -35,7 +31,7 @@ public void updateHeight(WindowInsetsCompat insets) { */ return; } - mHeight = (int) PixelUtil.toDIPFromPixel(keyboardHeightDip); + mHeight = keyboardHeight; } public void onAnimationStart() { diff --git a/android/src/main/java/com/swmansion/reanimated/keyboard/WindowsInsetsManager.java b/android/src/main/java/com/swmansion/reanimated/keyboard/WindowsInsetsManager.java index b7ad125e9c8..d1077547bde 100644 --- a/android/src/main/java/com/swmansion/reanimated/keyboard/WindowsInsetsManager.java +++ b/android/src/main/java/com/swmansion/reanimated/keyboard/WindowsInsetsManager.java @@ -1,24 +1,47 @@ package com.swmansion.reanimated.keyboard; +import android.graphics.Color; import android.os.Handler; import android.os.Looper; import android.view.View; +import android.view.ViewTreeObserver; import android.view.Window; import android.widget.FrameLayout; import androidx.core.view.ViewCompat; import androidx.core.view.WindowCompat; import androidx.core.view.WindowInsetsCompat; import com.facebook.react.bridge.ReactApplicationContext; -import com.swmansion.reanimated.BuildConfig; import java.lang.ref.WeakReference; public class WindowsInsetsManager { private boolean mIsStatusBarTranslucent = false; + + private int statusBarHeight = 0; + private int paddingTop = 0; + + private int paddingBottom = 0; private final WeakReference mReactContext; private final Keyboard mKeyboard; private final NotifyAboutKeyboardChangeFunction mNotifyAboutKeyboardChange; + private final ViewTreeObserver.OnDrawListener statusBarChangeListener = + new ViewTreeObserver.OnDrawListener() { + @Override + public void onDraw() { + View statusBar = getStatusBarView(); + int currentStatusBarHeight = statusBar.getHeight(); + boolean isStatusBarTranslucent = getWindow().getStatusBarColor() == Color.TRANSPARENT; + + if (isStatusBarTranslucent != mIsStatusBarTranslucent + || currentStatusBarHeight != statusBarHeight) { + mIsStatusBarTranslucent = isStatusBarTranslucent; + statusBarHeight = currentStatusBarHeight; + updateInsets(paddingTop, paddingBottom); + } + } + }; + public WindowsInsetsManager( WeakReference reactContext, Keyboard keyboard, @@ -36,10 +59,16 @@ private View getRootView() { return getWindow().getDecorView(); } + private View getStatusBarView() { + return getWindow().findViewById(android.R.id.statusBarBackground); + } + public void startObservingChanges( KeyboardAnimationCallback keyboardAnimationCallback, boolean isStatusBarTranslucent) { mIsStatusBarTranslucent = isStatusBarTranslucent; updateWindowDecor(false); + + getStatusBarView().getViewTreeObserver().addOnDrawListener(statusBarChangeListener); ViewCompat.setOnApplyWindowInsetsListener(getRootView(), this::onApplyWindowInsetsListener); ViewCompat.setWindowInsetsAnimationCallback(getRootView(), keyboardAnimationCallback); } @@ -47,9 +76,10 @@ public void startObservingChanges( public void stopObservingChanges() { updateWindowDecor(!mIsStatusBarTranslucent); updateInsets(0, 0); - View rootView = getRootView(); - ViewCompat.setWindowInsetsAnimationCallback(rootView, null); - ViewCompat.setOnApplyWindowInsetsListener(rootView, null); + + getStatusBarView().getViewTreeObserver().removeOnDrawListener(statusBarChangeListener); + ViewCompat.setWindowInsetsAnimationCallback(getRootView(), null); + ViewCompat.setOnApplyWindowInsetsListener(getRootView(), null); } private void updateWindowDecor(boolean decorFitsSystemWindow) { @@ -58,24 +88,19 @@ private void updateWindowDecor(boolean decorFitsSystemWindow) { } private WindowInsetsCompat onApplyWindowInsetsListener(View view, WindowInsetsCompat insets) { + WindowInsetsCompat defaultInsets = ViewCompat.onApplyWindowInsets(view, insets); if (mKeyboard.getState() == KeyboardState.OPEN) { mKeyboard.updateHeight(insets); mNotifyAboutKeyboardChange.call(); } - setWindowInsets(insets); - return insets; + setWindowInsets(defaultInsets); + return defaultInsets; } private void setWindowInsets(WindowInsetsCompat insets) { - int paddingBottom = 0; - boolean isOldPaperImplementation = - !BuildConfig.IS_NEW_ARCHITECTURE_ENABLED && BuildConfig.REACT_NATIVE_MINOR_VERSION < 70; - if (isOldPaperImplementation) { - int navigationBarTypeMask = WindowInsetsCompat.Type.navigationBars(); - paddingBottom = insets.getInsets(navigationBarTypeMask).bottom; - } int systemBarsTypeMask = WindowInsetsCompat.Type.systemBars(); - int paddingTop = insets.getInsets(systemBarsTypeMask).top; + paddingTop = insets.getInsets(systemBarsTypeMask).top; + paddingBottom = insets.getInsets(systemBarsTypeMask).bottom; updateInsets(paddingTop, paddingBottom); } @@ -94,8 +119,8 @@ private FrameLayout.LayoutParams getLayoutParams(int paddingTop, int paddingBott int matchParentFlag = FrameLayout.LayoutParams.MATCH_PARENT; FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(matchParentFlag, matchParentFlag); - if (mIsStatusBarTranslucent) { - params.setMargins(0, 0, 0, 0); + if (mIsStatusBarTranslucent || statusBarHeight == 0) { + params.setMargins(0, 0, 0, paddingBottom); } else { params.setMargins(0, paddingTop, 0, paddingBottom); }