ArturKalach / react-native-external-keyboard

React native library for physical keyboard support
MIT License
26 stars 4 forks source link

Moving between items #48

Open oleksii-ilchenko opened 3 weeks ago

oleksii-ilchenko commented 3 weeks ago

Hello!

Is it possible to move between items in list with the help of 0-9 num buttons? For example pressed button 0 moves focus to first item in list, 1 - to second and so on

Thanks a lot for answer!

ArturKalach commented 3 weeks ago

Hello, it's possible, but it could be really challenging.

To implement this, many steps need to be taken, and there are also a lot of nuances. Let’s start with the nuances:

Challenges:

I could give it a try later, but I can't say when.

oleksii-ilchenko commented 3 weeks ago

Hello, it's possible, but it could be really challenging.

To implement this, many steps need to be taken, and there are also a lot of nuances. Let’s start with the nuances:

  • Is the list a VirtualList or ScrollView?
  • Are the items common types like touchable|pressable, or could there be nesting?

Challenges:

  • First, capturing the key press seems tricky. It looks like it should be done globally, perhaps with a bubbling key press event, but it might be better to use a different API.
  • Second, proper focus handling. It's outdated at the moment, but I'm preparing a new release.
  • Lastly, if it's a ScrollView, there could be issues with scrolling. The component needs to be visible within the screen frame to be focused.

I could give it a try later, but I can't say when.

Thanks for quick reply! 1 - its ScrollView 2 - common Pressable (KeyboardExtendedPressable from your library)

ArturKalach commented 2 days ago

Hello @oleksii-ilchenko, Finally, I released a new version that may help with your question. The new version includes updated functionality for component focusing, allowing us to easily focus on components using a ref.current.focus action.

This means that only two things are needed to do for implemnting the logic you've described above:

Global key handling

First, I recommend trying these libraries:

Scrolling

Whether you need to control scrolling depends on the content of your ScrollView and whether everything fits within the visible frame. In some cases, scrolling may not be necessary, but if I'm not mistaken, React Native already provides built-in scrolling functionality.

For example:

 scrollViewRef.current.scrollTo({ y: y, animated: true });

Or you could try https://github.com/slorber/react-native-scroll-into-view

Focus

The final step is focusing on the component. For example:


import GlobalKeyEvent from 'react-native-global-keyevent';
import {
  Pressable,
  KeyboardFocus,
} from 'react-native-external-keyboard';

export const Example = () => {
  const firstRef = React.useRef<KeyboardFocus>(null);
  const secondRef = React.useRef<KeyboardFocus>(null);
  const scrollViewRef = React.useRef<ScrollView>(null);

  const refMap = {
    '1': firstRef,
    '2': secondRef,
  };
  const onFocusByPress = (key: string) => {
    const targetRef = refMap?.[key];
    if (!targetRef?.current || !scrollViewRef.current) return;

    targetRef.current.measure((_x: number, y: number) => {
      scrollViewRef.current?.scrollTo({ y: y, animated: true });
      //maybe dellay to be sure that the view on the view point
      targetRef.current.focus();
    });
  };
  React.useEffect(() => {
    GlobalKeyEvent.addKeyUpListener((evt) => onFocusByPress(evt.pressedKey));

    // Probably something to remove listener
    return () => {}
  }, []);

  return (
    <ScrollView ref={scrollViewRef}>
      <Pressable ref={firstRef} />
      <Pressable ref={secondRef} />
    </ScrollView>
  );
};

I think this would be the best and only correct way to do it. Scrolling and global key handling could be good ideas to work on, but there are already existing solutions, and I’m not sure if it would be possible and easy to find better solution.