-
-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: own
useWindowDimensions
hook (#468)
## 📜 Description Implemented own `useWindowDimensions` hook for Android. ## 💡 Motivation and Context The problem with default implementation of `useWindowDimensions` on Android is that it doesn't work well with `edge-to-edge` mode and you can not retrieve an actual size of the screen. Here is a brief comparison of values captured on my device (Pixel 7 Pro). Translucent `StatusBar`: ```sh height: 867.4285888671875 <- own hook height: 867.4285888671875, y: 0 <- useSafeAreaFrame height: 891.4285714285714 <- Dimensions.get('screen') height: 826.2857142857143 <- Dimensions.get('window') ``` Non translucent `StatusBar`: ```sh height: 867.4285888671875 <- own hook height: 826.2857055664062, y: 41.14285659790039 <- useSafeAreaFrame height: 891.4285714285714 <- Dimensions.get('screen') height: 826.2857142857143 <- Dimensions.get('window') ``` So as you can see it doesn't react properly on the case when `StatusBar` is translucent and reports incorrect values, which later on causes incorrect layout calculation in components like `KeyboardAvoidingView` or `KeyboardAwareScrollView`. Theoretically we could workaround this problem by original `useWindowDimensions().height + StatusBar.currentHeight`, but everything become trickier when we add translucent `navigationBar` (+ translucent `statusBar`): ```sh height: 891.4285888671875 <- own hook height: 891.4285888671875, y: 0 <- useSafeAreaFrame height: 891.4285714285714 <- Dimensions.get('screen') height: 826.2857142857143 <- Dimensions.get('window') ``` In this case derived value `useWindowDimensions().height + StatusBar.currentHeight` (867.4285888671875) still will produce incorrect value and all calculations will be broken. So I decided to create own version of the hook which will cover all the cases. Issue for reference: facebook/react-native#41918 Closes #434 #334 ## 📢 Changelog <!-- High level overview of important changes --> <!-- For example: fixed status bar manipulation; added new types declarations; --> <!-- If your changes don't affect one of platform/language below - then remove this platform/language --> ### JS - export own `useWindowDimensions` hook; - started to use own `useWindowDimensions` in `KeyboardAwareScrollView` and `KeyboardAvoidingView` components; - added mock for `useWindowDimensions` hook as default RN implementation; ### Android - added `WindowDimensionsListener` class; - added `ThemedReactContext.content` extension; - added `ThemedReactContext.setupWindowDimensionListener` extension; ## 🤔 How Has This Been Tested? Tested manually on Pixel 7 Pro (API 34). Tested on CI via e2e (API 28). ## 📸 Screenshots (if appropriate): Pixel 7 Pro (Android 14), `KeyboardAwareScrollView`: ### KeyboardAwareScrollView |Before|After| |-------|-----| |![telegram-cloud-photo-size-2-5429580266013318443-y](https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/4874f962-2726-4cd0-ba96-4b57c076b6f5)|![telegram-cloud-photo-size-2-5429580266013318444-y](https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/28a3b276-f8b7-40fa-a17d-bcc4e58b28b7)| ### KeyboardAvoidingView |Initial|Before|After| |------|------|-----| |![telegram-cloud-photo-size-2-5429580266013318470-y](https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/570d0092-c846-4005-97b0-c596169b91f8)|![telegram-cloud-photo-size-2-5429580266013318469-y](https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/8909fee6-aa42-45a3-87b6-65c59831c703)|![telegram-cloud-photo-size-2-5429580266013318471-y](https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/e64c5dfd-cdc1-4cf5-b731-3a25d3a2fde3)| ## 📝 Checklist - [x] CI successfully passed - [x] I added new mocks and corresponding unit-tests if library API was changed
- Loading branch information
1 parent
97d504d
commit 817127f
Showing
12 changed files
with
146 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
android/src/main/java/com/reactnativekeyboardcontroller/listeners/WindowDimensionListener.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package com.reactnativekeyboardcontroller.listeners | ||
|
||
import android.view.ViewGroup | ||
import androidx.core.view.marginTop | ||
import com.facebook.react.bridge.Arguments | ||
import com.facebook.react.uimanager.ThemedReactContext | ||
import com.reactnativekeyboardcontroller.extensions.content | ||
import com.reactnativekeyboardcontroller.extensions.dp | ||
import com.reactnativekeyboardcontroller.extensions.emitEvent | ||
|
||
data class Dimensions(val width: Double, val height: Double) | ||
|
||
class WindowDimensionListener(private val context: ThemedReactContext?) { | ||
private var lastDispatchedDimensions = Dimensions(0.0, 0.0) | ||
|
||
init { | ||
// attach to content view only once | ||
if (!isListenerAttached) { | ||
isListenerAttached = true | ||
|
||
val content = context?.content | ||
|
||
updateWindowDimensions(content) | ||
|
||
content?.viewTreeObserver?.addOnGlobalLayoutListener { | ||
updateWindowDimensions(content) | ||
} | ||
} | ||
} | ||
|
||
private fun updateWindowDimensions(content: ViewGroup?) { | ||
if (content == null) { | ||
return | ||
} | ||
|
||
val newDimensions = Dimensions( | ||
content.width.toFloat().dp, | ||
content.height.toFloat().dp + content.marginTop.toFloat().dp, | ||
) | ||
|
||
if (newDimensions != lastDispatchedDimensions) { | ||
lastDispatchedDimensions = newDimensions | ||
|
||
context.emitEvent( | ||
"KeyboardController::windowDidResize", | ||
Arguments.createMap().apply { | ||
putDouble("height", newDimensions.height) | ||
putDouble("width", newDimensions.width) | ||
}, | ||
) | ||
} | ||
} | ||
|
||
companion object { | ||
private var isListenerAttached = false | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { useEffect, useState } from "react"; | ||
|
||
import { WindowDimensionsEvents } from "../../bindings"; | ||
|
||
import type { WindowDimensionsEventData } from "../../types"; | ||
|
||
let initialDimensions: WindowDimensionsEventData = { | ||
width: 0, | ||
height: 0, | ||
}; | ||
|
||
WindowDimensionsEvents.addListener("windowDidResize", (e) => { | ||
initialDimensions = e; | ||
}); | ||
|
||
export const useWindowDimensions = () => { | ||
const [dimensions, setDimensions] = useState(initialDimensions); | ||
|
||
useEffect(() => { | ||
const subscription = WindowDimensionsEvents.addListener( | ||
"windowDidResize", | ||
(e) => { | ||
setDimensions(e); | ||
}, | ||
); | ||
|
||
return () => { | ||
subscription.remove(); | ||
}; | ||
}, []); | ||
|
||
return dimensions; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { useWindowDimensions } from "react-native"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters