Skip to content

Fix measureInWindow on Android edge-to-edge#56056

Open
zoontek wants to merge 2 commits intofacebook:mainfrom
zoontek:fix-measure-in-window
Open

Fix measureInWindow on Android edge-to-edge#56056
zoontek wants to merge 2 commits intofacebook:mainfrom
zoontek:fix-measure-in-window

Conversation

@zoontek
Copy link
Contributor

@zoontek zoontek commented Mar 11, 2026

Summary:

⚠️ Note: This relies on #56055 being merged first.

Fixes measureInWindow on Android when edge-to-edge is enabled.

Both ReactSurfaceView.viewportOffset and RootViewUtil.getViewportOffset subtract the visible window frame (status bar insets, split screen offsets) from getLocationOnScreen / getLocationInWindow coordinates. This is incorrect in edge-to-edge mode, where the content already extends behind system bars.

Related issue: #50509

Changelog:

[ANDROID] [FIXED] - Fix measureInWindow returning incorrect coordinates when edge-to-edge is not enabled

Test Plan:

Tested measureInWindow with and without edge-to-edge enabled, in both single-window and split-screen configurations. Verified that returned coordinates correctly reflect the view's position relative to the visible content area.

For that, in RNTesterActivity.kt, comment:

// reactDelegate?.reactRootView?.let { rootView ->
//   val insetsType: Int =
//       WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout()

//   val windowInsetsListener = { view: View, windowInsets: WindowInsetsCompat ->
//     val insets = windowInsets.getInsets(insetsType)

//     (view.layoutParams as FrameLayout.LayoutParams).apply {
//       setMargins(insets.left, insets.top, insets.right, insets.bottom)
//     }

//     WindowInsetsCompat.CONSUMED
//   }
//   ViewCompat.setOnApplyWindowInsetsListener(rootView, windowInsetsListener)
// }

And in RNTesterAppShared.js replace export default RNTesterApp with:

export default () => {
  const ref = React.useRef<View>(null);
  const [measure, setMeasure] = React.useState<string>('');
  const [measureInWindow, setMeasureInWindow] = React.useState<string>('');
  const [onLayoutOutput, setOnLayoutOutput] = React.useState<string>('');
  React.useLayoutEffect(() => {
    ref.current?.measure(
      (
        x: number,
        y: number,
        width: number,
        height: number,
        pageX: number,
        pageY: number,
      ) => {
        setMeasure(
          `(${x}, ${y}) / ${width} x ${height}; \n  page=(${pageX}, ${pageY})`,
        );
      },
    );
  }, []);
  React.useLayoutEffect(() => {
    ref.current?.measureInWindow(
      (x: number, y: number, width: number, height: number) => {
        setMeasureInWindow(`(${x}, ${y}) / ${width} x ${height};})`);
      },
    );
  }, []);
  return (
    <View
      ref={ref}
      style={{flex: 1, justifyContent: 'center'}}
      onLayout={e => {
        setOnLayoutOutput(JSON.stringify(e.nativeEvent.layout));
      }}>
      <Text>Measure: {measure}</Text>
      <Text>measureInWindow: {measureInWindow}</Text>
      <Text>onLayout: {onLayoutOutput}</Text>
    </View>
  );
};

Screenshots:

Android 16 / edge-to-edge on - current behavior

Android 16 (edge-to-edge on - no fix)

Android 16 / edge-to-edge on - with fix

Android 16 (edge-to-edge on - fixed)

Android 14 / edge-to-edge off - current behavior

Android 14 (edge-to-edge off - no fix)

Android 14 / edge-to-edge off - with fix (no change)

Android 14 (edge-to-edge off - fixed)

@meta-cla meta-cla bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Mar 11, 2026
@facebook-github-bot facebook-github-bot added p: Expo Partner: Expo Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. labels Mar 11, 2026
@zoontek zoontek force-pushed the fix-measure-in-window branch from 04d84f8 to f165005 Compare March 11, 2026 14:04
kirillzyusko added a commit to kirillzyusko/react-native-keyboard-controller that referenced this pull request Mar 12, 2026
## 📜 Description

Fixed broken `measureInWindow` measurements in react-native.

## 💡 Motivation and Context

The `measureInWindow` works unreliably in Fabric + formSheet Modal
(facebook/react-native#56062) or on Android with
edge-to-edge enabled
(facebook/react-native#56056)

Upstream fixes are available, but the problem is that it will require at
least RN 0.85+ to work properly. So in this PR we add internal function
that is capable of measuring given view. In future this functionality
can be removed, but for now this is critical to have it bundled within a
package.

Fixes
#1356

## 📢 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

- added `viewPositionInWindow` to `types`;
- added `viewPositionInWindow` to codegen;
- added `viewPositionInWindow` to bindings/module;
- use `viewPositionInWindow` instead of `measureInWindow`;
- added `viewPositionInWindow` to mocks;

### iOS

- implement `viewPositionInWindow`;
- make `activeWindow` objc available;

### Android

- implement `viewPositionInWindow`;
- add `uiManager` and `eventDispatcher` to `ReactContext` extensions;

## 🤔 How Has This Been Tested?

Tested manually on iPhone 17 Pro (iOS 26.2, simulator) and Pixel 9 Pro
(API 35, emulator).

## 📸 Screenshots (if appropriate):

### Android

#### Fabric

|Before|After|
|-------|-----|
|<video
src="https://github.com/user-attachments/assets/afb99e51-043f-459c-90e3-7e1eb1e184ed">|<video
src="https://github.com/user-attachments/assets/8ea0d593-f7bd-47a5-9343-e2fd85f4af45">|

#### Paper

|Before|After|
|-------|-----|
|<video
src="https://github.com/user-attachments/assets/702c7d88-755b-45f0-b39f-fe4aaa60ab2e">|<video
src="https://github.com/user-attachments/assets/f5346bbd-cc85-4a40-9cc5-9422931b04af">|

### iOS

#### Fabric

|Before|After|
|-------|-----|
|<video
src="https://github.com/user-attachments/assets/49fb9ac6-15b8-4842-939c-4ec06a4e0c42">|<video
src="https://github.com/user-attachments/assets/b559a52a-0a91-48bc-911a-7125ce96e013">|

#### Paper

|Before|After|
|-------|-----|
|<video
src="https://github.com/user-attachments/assets/c4d234a7-122a-4023-8d86-fad71ed043dc">|<video
src="https://github.com/user-attachments/assets/d5d48487-16ad-40c2-b6c6-fea85b563e20">|

## 📝 Checklist

- [x] CI successfully passed
- [x] I added new mocks and corresponding unit-tests if library API was
changed

---------

Co-authored-by: thomasvo <thomas.vo@openspace.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: kirillzyusko <zyusko.kirik@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Expo Partner: Expo Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants