Skip to content

iOS: safeAreaInsets not propagated to child UIKit views — contentInsetAdjustmentBehavior broken #1086

@IsaacIsrael

Description

@IsaacIsrael

Bug

contentInsetAdjustmentBehavior has no effect on UIScrollView instances (including FlashList / FlatList) embedded inside PagerView pages. Scroll views report safeAreaInsets = .zero, so they cannot automatically adjust content insets for overlapping system chrome (e.g. translucent tab bars on iOS 26 liquid glass).

Environment

  • react-native-pager-view: 8.0.0
  • React Native: 0.78
  • iOS: 26 (liquid glass translucent tab bar with drawBehind: true)
  • Architecture: New Architecture (Fabric)

Steps to reproduce

  1. Use a bottom tab navigator with drawBehind: true and a translucent tab bar (iOS 26 liquid glass)
  2. Place a PagerView inside a tab screen
  3. Add a scrollable list (e.g. FlashList or FlatList) inside a PagerView page
  4. Set contentInsetAdjustmentBehavior='scrollableAxes' on the scroll view
  5. Scroll to the bottom of the list

Expected: Last item stops above the tab bar (scroll view adds ~83pt bottom content inset automatically)

Actual: Last items are hidden behind the tab bar. The scroll view's adjustedContentInset.bottom remains 0.

Root cause

The UIHostingController is initialized with ignoreSafeArea: true (PagerViewProvider.swift L109-111), which calls disableSafeArea() and dynamically subclasses the hosting view to override safeAreaInsets.zero.

Even without ignoreSafeArea, RepresentableView uses UIViewRepresentable which embeds a plain wrapper UIView. SwiftUI does not propagate safe area insets through UIViewRepresentable — the wrapper and all its descendant UIKit views see safeAreaInsets = .zero.

Debug log evidence (added print statements to trace the view hierarchy):

HostingController.view.safeAreaInsets: bottom: 83     ← correct at hosting level
PagingCollectionView.safeAreaInsets:   bottom: 83     ← correct at TabView collection
Wrapper UIView.safeAreaInsets:         bottom: 0      ← LOST HERE (UIViewRepresentable boundary)
RCTEnhancedScrollView.safeAreaInsets:  bottom: 0      ← zero → contentInsetAdjustmentBehavior noop
  contentInsetAdjustmentBehavior: 2 (scrollableAxes)
  adjustedContentInset: bottom: 0                     ← no adjustment despite scrollableAxes

Proposed fix

PR #1085 addresses this with three changes:

  1. Replace UIViewRepresentableUIViewControllerRepresentable with a PageChildViewController that reads the hosting view's real safeAreaInsets and re-injects them via additionalSafeAreaInsets
  2. Add .ignoresSafeArea() to the SwiftUI TabView body so pages extend behind system chrome
  3. Remove ignoreSafeArea: true from UIHostingController init so the hosting view preserves real insets

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions