Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moving between items #48

Open
oleksii-ilchenko opened this issue Oct 11, 2024 · 3 comments
Open

Moving between items #48

oleksii-ilchenko opened this issue Oct 11, 2024 · 3 comments

Comments

@oleksii-ilchenko
Copy link

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
Copy link
Owner

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.

@oleksii-ilchenko
Copy link
Author

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
Copy link
Owner

ArturKalach commented Nov 3, 2024

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
  • Scrolling the ScrollView to the component

Global key handling

First, I recommend trying these libraries:

I thought about writing my own library, but there’s likely nothing I can make really different... Perhaps adding support for the New Architecture would be beneficial, but it might be better to contribute directly to an existing library.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants