react-native-avoid-softinput icon indicating copy to clipboard operation
react-native-avoid-softinput copied to clipboard

Is there a way to scroll the screen on top of the keyboard for the multi line input?

Open Saad-Bashar opened this issue 2 years ago • 4 comments

Feature request

Thanks for this amazing library! I have a question. I have a multiline text input. The keyboard avoid is working great. But let's say the user keeps writing and go to the next line and exceeds the viewport, the text gets overlapped by the keyboard. Users can scroll down manually again to see the new line. Is there a way to automatically scroll the screen to the new line that got overlapped by the keyboard? Please check the demo video

https://user-images.githubusercontent.com/13269141/227155257-e1a7c77d-4a0d-424e-bcfa-e11a08ec1529.mov

Saad-Bashar avatar Mar 23 '23 09:03 Saad-Bashar

Hi @Saad-Bashar, thx for asking the question.

In your case, I guess that you display your input inside a ScrollView - in that case OS doesn't emit any notification indicating that the keyboard height changed, or the input's cursor is being covered. The library depends on the keyboard events and I'm afraid it's out of the library's scope to handle what IMO should be handled by OS.

The only thing I can suggest here is to refactor the way the keyboard padding is applied, however, I am not sure if the final UX will be satisfying for you. Currently, the library is applying the padding to the Scrollview where your multiline input is displayed. You could try to apply the padding manually at the bottom of the screen (you can look at this recipe - instead of button, you would just have empty spacer element at the bottom). That way, you will be sure that the ScrollView bounds are always above the keyboard and in theory, OS should automatically handle your input. The downside is that when keyboard is dismissed, the blank spacer may be visible for a fraction of a second. You have to check yourself if the final effect is feasible.

I'll the issue open for a while, as I'm curious, if there're more people affected.

mateusz1913 avatar Mar 23 '23 10:03 mateusz1913

I tried that however still the text was getting overlapped by the keyboard. This seems like a famous issue, https://github.com/facebook/react-native/issues/16826

Saad-Bashar avatar Mar 24 '23 06:03 Saad-Bashar

I'm think this works with lib, however I'm not 100%.

a-eid avatar Mar 31 '23 21:03 a-eid

@Saad-Bashar , I solved the same issue by following steps.

For multiline textinput, I wrap the input in view and add listen to onLayout change. As I get difference in the height, I use scrollTo method of Scrollview to scroll programmatically.

function useSoftInputKeyboard(scrollRef: RefObject<ScrollView>, scrollYRef: RefObject<number>) {
  const booleanRef = useRef(false);
  const inputHeightRef = useRef<number>(0);

  const onFocus = useCallback(() => {
    booleanRef.current = true;
  }, []);

  const onBlur = useCallback(() => {
    booleanRef.current = false;
  }, []);

  const inputOnLayoutView = useCallback(
    (isMultiLine = false) =>
      ({
        nativeEvent: {
          layout: { height },
        },
      }: LayoutChangeEvent) => {
        if (isMultiLine && booleanRef.current) {
          scrollRef.current?.scrollTo({ y: (scrollYRef.current ?? 0) + (height - inputHeightRef.current) });
          inputHeightRef.current = height;
        }
      },
    [scrollRef, scrollYRef],
  );

  return {
    onFocus,
    onBlur,
    inputOnLayoutView,
  };
}

saadi-ninjasCode avatar Nov 08 '23 12:11 saadi-ninjasCode