callstack / react-native-pager-view

React Native wrapper for the Android ViewPager and iOS UIPageViewController.
MIT License
2.7k stars 415 forks source link

I would like the Height to be scaled according to the children #532

Open yepMad opened 2 years ago

yepMad commented 2 years ago

Describe the feature

I saw that there are numerous issues saying that the height of the PagerView is not according to the height of the children. I wish it was. Is it possible to implement this in the current source code architecture? Is there any direction? I would like to do a PR with this, but first I wanted to know if it's possible.

I saw the workarounds and in my use case they are not enough.

Motivation

I have several pages that have varying sizes. I use LazyPagerView from the new Pre-Release version, so I can't consider the highest height of the first pages.

Related Issues

https://github.com/callstack/react-native-pager-view/issues/436 https://github.com/callstack/react-native-pager-view/issues/386

yepMad commented 2 years ago

@troZee If you can help me with this I would be very grateful.

elmcapp commented 2 years ago

Describe the feature

I saw that there are numerous issues saying that the height of the PagerView is not according to the height of the children. I wish it was. Is it possible to implement this in the current source code architecture? Is there any direction? I would like to do a PR with this, but first I wanted to know if it's possible.

I saw the workarounds and in my use case they are not enough.

Motivation

I have several pages that have varying sizes. I use LazyPagerView from the new Pre-Release version, so I can't consider the highest height of the first pages.

Related Issues

436 #386

I am having same issue. Check out the video I made on issue #531.

I found a fix for the issue. Would be nice if @troZee could patch this for us. Go to file path: node_modules/react-native-pager-view/scr/utils.tsx
comment out line 30 and 31

currently

export const childrenWithOverriddenStyle = (children?: ReactNode) => {
  // Override styles so that each page will fill the parent. Native component
  // will handle positioning of elements, so it's not important to offset
  // them correctly.
  return Children.map(children, (child) => {
    const { props } = child as ReactElement;
    const newProps = {
      ...props,
      style: [
        props.style,
        {
          position: 'absolute',
          flex:1,
          left: 0,
          top: 0,
          right: 0,
          bottom: 0,
          width: undefined,
          height: undefined,
        },
      ],
      collapsable: false,
    };
    return React.cloneElement(child as ReactElement, newProps);
  });
};

to

export const childrenWithOverriddenStyle = (children?: ReactNode) => {
  // Override styles so that each page will fill the parent. Native component
  // will handle positioning of elements, so it's not important to offset
  // them correctly.
  return Children.map(children, (child) => {
    const { props } = child as ReactElement;
    const newProps = {
      ...props,
      style: [
        props.style,
        {
          position: 'absolute',
          flex:1,
          left: 0,
          top: 0,
          right: 0,
          bottom: 0,
          // width: undefined,
          // height: undefined,
        },
      ],
      collapsable: false,
    };
    return React.cloneElement(child as ReactElement, newProps);
  });
};

solved my issue

xmflsct commented 2 years ago

It is not related to the js part. Rolling back to 5.4.11 fixed the issue.

jason-vault commented 2 years ago

Rolling back to 5.4.13 fixed for me.

mmxdr commented 2 years ago

managed to solve this using measureLayout

export const MainSlider: FunctionComponent<Props> = ({ slides }) => {
  const [height, setHeight] = useState<number | string>('100%');
  const parentRefs = useMemo<RefObject<View>[]>(
    () => Array.from({ length: slides.length }).map(() => createRef()),
    [],
  );
  const childRefs = useMemo<RefObject<View>[]>(
    () => Array.from({ length: slides.length }).map(() => createRef()),
    [],
  );

  return (
      <PagerView
        style={{ height: height }}
        initialPage={0}
        orientation="horizontal"
        onPageSelected={(e) => {
          const { position } = e.nativeEvent;

          childRefs[position].current?.measureLayout(
            findNodeHandle(parentRefs[position].current),
            (x, y, width, height) => {
              console.log('got measurement', x, y, width, height);
              setHeight(height);
            },
            () => {
              console.log('measureLayout error')
            },
          );
        }}
      >
        {slides?.map((slide, index) => (
          <View key={index}>
            <View ref={parentRefs[index]}>
              <View ref={childRefs[index]}>
                {variable height content}
              </View>
            </View>
          </View>
        ))}
      </PagerView>
  );
};
fukemy commented 1 year ago

@mmxdr too many variable required for this solution

Seamus1989 commented 5 months ago

I use this library in two places. One in a standard page, and another inside a modal (which has an internal scrollview). It seems rolling back the version lets it work with the modal, but then breaks my standard use case?!?!?

qaezrun commented 2 weeks ago

Hello has anyone found solution for this?