callstack / react-native-pager-view

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

setPage prevents Keyboard on Android #514

Open adam-adair opened 2 years ago

adam-adair commented 2 years ago

Environment

"expo": "~44.0.0", "react": "17.0.1", "react-native": "0.64.3", "react-native-pager-view": "5.4.9",

OS: Ubuntu 20.04 Device OS: Android 11

Description

setPage prevents initial keyboard open on any PagerView child View except for the first and last.

In my testing, this only occurs on Android and only when the keyboard is not on screen when setPage is called. It does not occur when setPageWithoutAnimation is called or when a page is selected by gesture rather than calling setPage.

Reproducible Demo

Snack reproducing bug

Repo reproducing bug

To reproduce the bug, on an Android device:

ecoriag commented 2 years ago

It seems this only happens with intermediate pages, first and last pages work as expected. Taking advantage of this, a work around I found is switching first and current pages quickly after paging completes, it works just well:

const selectedPage = React.useRef(0);
...
<PagerView
  onPageSelected={(e) => {
    selectedPage.current = e.nativeEvent.position;
  }}
  onPageScrollStateChanged={(e) => {
    if (e.nativeEvent.pageScrollState == 'idle') {
      pagerRef.current?.setPageWithoutAnimation(0);
      pagerRef.current?.setPageWithoutAnimation(selectedPage.current);
    }
  }}
>
stefandbd commented 2 years ago

@ecoriag your solution didn't work for me :( (but that is indeed the behaviour that happens on android - middle screens keyboard flickering) @troZee do we have any updates for this one? It might be fixed on the pre-release 6.0.0 rc1? (there are some differences and some new things there as I checked...)

Thanks

danilvalov commented 2 years ago

The same problem in v.5.4.15.

@ecoriag It works for me, thanks! But it's ok as temporary solution only.

I hope it will be fixed in stable v6

marwane1b3 commented 2 years ago

@ecoriag your solution worked perfectly for my case thanks

aryatama commented 1 year ago

It seems this only happens with intermediate pages, first and last pages work as expected. Taking advantage of this, a work around I found is switching first and current pages quickly after paging completes, it works just well:

const selectedPage = React.useRef(0);
...
<PagerView
  onPageSelected={(e) => {
    selectedPage.current = e.nativeEvent.position;
  }}
  onPageScrollStateChanged={(e) => {
    if (e.nativeEvent.pageScrollState == 'idle') {
      pagerRef.current?.setPageWithoutAnimation(0);
      pagerRef.current?.setPageWithoutAnimation(selectedPage.current);
    }
  }}
>

OMG Thank you brooooooo 😭

Hrfreire commented 2 months ago

In my case, the fix suggested by ecoriag was causing a flicker on the page.

This fixed the issue for me: (without the flickering)

  const setPage = (index: number) => {
    if (pagerRef?.current) {
      pagerRef?.current.setPage(index);

      if (Platform.OS === 'android') {
        pagerRef.current?.setPageWithoutAnimation(index);
      }
    }
  };

Since this issue only occurs when calling the method with animation, I tried to call the method without the animation after the method with animation and it seems to work well. In that way, the animation of the first method works, and call the second method seems to avoid the issue caused by the animated method.