React-native-screens: How to measure header height?

Created on 20 Mar 2020  路  8Comments  路  Source: software-mansion/react-native-screens

I implement padding to KeyboardAvoidingView.
In react-navigation I could get header height through useHeaderHeight hook.

import { useHeaderHeight } from '@react-navigation/stack';

// ...

const headerHeight = useHeaderHeight();

Could you mind share ideas to measure that header height?

enhancement

Most helpful comment

Hi, I use useSafeArea and add value for default platform:

import * as React from 'react';
import { KeyboardAvoidingView, KeyboardAvoidingViewProps } from 'react-native';
import { useSafeArea } from 'react-native-safe-area-view';

type Props = KeyboardAvoidingViewProps & {
  children: React.ReactNode;
  extraOffset?: number;
};
const isIOS = Platform.OS == 'ios'
const HEADER_HEIGHT = Platform.OS === 'ios' ? 44 : 56;

const KeyboardAvoiding: React.FC<Props> = React.memo(({ children, extraOffset, ...rest }: Props) => {
  const insets = useSafeArea();

  return (
    <KeyboardAvoidingView
      keyboardVerticalOffset={insets.top + HEADER_HEIGHT + (extraOffset as number)}
      behavior={isIOS ? 'padding' : undefined}
      enabled
      {...rest}
    >
      {children}
    </KeyboardAvoidingView>
  );
});

KeyboardAvoiding.displayName = 'KeyboardAvoiding';
KeyboardAvoiding.defaultProps = {
  extraOffset: 0,
};

export default KeyboardAvoiding;

This works with headerLargeTitle=true ??, and what extraOffset is I don't understand that part , if you could help me please thanks!!!

Not working with headerLargeTitle, and extraOffset working with tabs or others components with you add

All 8 comments

Hey there

Hi, I use useSafeArea and add value for default platform:

import * as React from 'react';
import { KeyboardAvoidingView, KeyboardAvoidingViewProps } from 'react-native';
import { useSafeArea } from 'react-native-safe-area-view';

type Props = KeyboardAvoidingViewProps & {
  children: React.ReactNode;
  extraOffset?: number;
};
const isIOS = Platform.OS == 'ios'
const HEADER_HEIGHT = Platform.OS === 'ios' ? 44 : 56;

const KeyboardAvoiding: React.FC<Props> = React.memo(({ children, extraOffset, ...rest }: Props) => {
  const insets = useSafeArea();

  return (
    <KeyboardAvoidingView
      keyboardVerticalOffset={insets.top + HEADER_HEIGHT + (extraOffset as number)}
      behavior={isIOS ? 'padding' : undefined}
      enabled
      {...rest}
    >
      {children}
    </KeyboardAvoidingView>
  );
});

KeyboardAvoiding.displayName = 'KeyboardAvoiding';
KeyboardAvoiding.defaultProps = {
  extraOffset: 0,
};

export default KeyboardAvoiding;

I hate to hijack this thread, but I've got a need to something similar to this description that is not solve-able via the react-native-safe-area-view. It seems at the moment if you measure a component when using this library

            UIManager.measureInWindow(this.handle, (x, y)

The y value differs when you're debugging vs not, the difference in measurement I believe is down to the navbar height not being taken into consideration. If this is indeed the case, having a way to get the total frame height would be really useful.

Hi, I use useSafeArea and add value for default platform:

import * as React from 'react';
import { KeyboardAvoidingView, KeyboardAvoidingViewProps } from 'react-native';
import { useSafeArea } from 'react-native-safe-area-view';

type Props = KeyboardAvoidingViewProps & {
  children: React.ReactNode;
  extraOffset?: number;
};
const isIOS = Platform.OS == 'ios'
const HEADER_HEIGHT = Platform.OS === 'ios' ? 44 : 56;

const KeyboardAvoiding: React.FC<Props> = React.memo(({ children, extraOffset, ...rest }: Props) => {
  const insets = useSafeArea();

  return (
    <KeyboardAvoidingView
      keyboardVerticalOffset={insets.top + HEADER_HEIGHT + (extraOffset as number)}
      behavior={isIOS ? 'padding' : undefined}
      enabled
      {...rest}
    >
      {children}
    </KeyboardAvoidingView>
  );
});

KeyboardAvoiding.displayName = 'KeyboardAvoiding';
KeyboardAvoiding.defaultProps = {
  extraOffset: 0,
};

export default KeyboardAvoiding;

This works with headerLargeTitle=true ??, and what extraOffset is I don't understand that part , if you could help me please thanks!!!

Hi, I use useSafeArea and add value for default platform:

import * as React from 'react';
import { KeyboardAvoidingView, KeyboardAvoidingViewProps } from 'react-native';
import { useSafeArea } from 'react-native-safe-area-view';

type Props = KeyboardAvoidingViewProps & {
  children: React.ReactNode;
  extraOffset?: number;
};
const isIOS = Platform.OS == 'ios'
const HEADER_HEIGHT = Platform.OS === 'ios' ? 44 : 56;

const KeyboardAvoiding: React.FC<Props> = React.memo(({ children, extraOffset, ...rest }: Props) => {
  const insets = useSafeArea();

  return (
    <KeyboardAvoidingView
      keyboardVerticalOffset={insets.top + HEADER_HEIGHT + (extraOffset as number)}
      behavior={isIOS ? 'padding' : undefined}
      enabled
      {...rest}
    >
      {children}
    </KeyboardAvoidingView>
  );
});

KeyboardAvoiding.displayName = 'KeyboardAvoiding';
KeyboardAvoiding.defaultProps = {
  extraOffset: 0,
};

export default KeyboardAvoiding;

This works with headerLargeTitle=true ??, and what extraOffset is I don't understand that part , if you could help me please thanks!!!

Not working with headerLargeTitle, and extraOffset working with tabs or others components with you add

Any thoughts on this issue? Currently looking into calculating the height of the header on iOS given that a largeTitle is supplied.

In my use case, it is to be able to scroll to the top of a ScrollView (with a proper inset calculation of the largeTitle) properly so that the largeTitle is shown.

I think the best way to do it is to use react-native-safe-area-context. On iOS, it should always be safeArea.top + 96 for large header and safeArea.top + 44 for small header. Does it solve your issue?

I haven't tested it on multiple configurations but it seems like it is calculated properly at 96 + inset.top. If I notice any issues, I'll make a comment.

Was this page helpful?
0 / 5 - 0 ratings