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

Allow two finger touchpad scrolling on iPadOS #1128

Merged
merged 10 commits into from
Nov 14, 2020

Conversation

robertherber
Copy link
Contributor

@robertherber robertherber commented Jul 15, 2020

Description

Adding support for touchpad in PanGestureHandler by setting allowedScrollTypesMask to UIScrollTypeMaskAll for all devices with iOS 13.4+. Important for iPads with Touchpads and should work with Mac Catalyst through the same API as well. As described in #1100 - this covers the ipadOS part of that issue.

Test plan

Run on an iPad with touchpad. It's now possible to two-finger swipe to interact with the PanGestureHandler.

Show code
import React from 'react';
import { AppRegistry, SafeAreaView, Animated } from 'react-native';
import { PanGestureHandler, State } from 'react-native-gesture-handler';

const Example = () => {
  const translateX = new Animated.Value(0);
  const translateY = new Animated.Value(0);
  const lastOffset = { x: 0, y: 0 };

  const onPanGestureEvent = Animated.event([
    {
      nativeEvent: {
        translationX: translateX,
        translationY: translateY,
      },
    },
  ]);

  const onHandlerStateChange = ({
    nativeEvent: { translationX, translationY, oldState },
  }) => {
    if (oldState === State.ACTIVE) {
      // compensate a start of pan
      lastOffset.x += translationX;
      lastOffset.y += translationY;
      translateX.setOffset(lastOffset.x);
      translateY.setOffset(lastOffset.y);

      translateX.setValue(0);
      translateY.setValue(0);
    }
  };

  return (
    <SafeAreaView style={styles.container}>
      <PanGestureHandler
        onGestureEvent={onPanGestureEvent}
        onHandlerStateChange={onHandlerStateChange}>
        <Animated.View
          style={[
            styles.rectangle,
            {
              transform: [{ translateX }, { translateY }],
            },
          ]}
        />
      </PanGestureHandler>
    </SafeAreaView>
  );
};

const styles = {
  container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
  rectangle: {
    backgroundColor: 'pink',
    width: 100,
    height: 100,
  },
};

AppRegistry.registerComponent('Example', () => Example);

@robertherber robertherber changed the title Touchpad scrolling Touchpad scrolling on iPadOS Jul 15, 2020
@jakub-gonet jakub-gonet self-assigned this Aug 23, 2020
@jakub-gonet
Copy link
Member

This breaks CI.

@robertherber
Copy link
Contributor Author

robertherber commented Sep 14, 2020

This breaks CI.

I'm guessing it's because the XCode used in the CI is 10.2 (current is 11.7) and this flag requires iOS 13 (which should require XCode 11 to build).

@jakub-gonet
Copy link
Member

I finally bumped CI and if checks will pass I'll merge this one.

@jakub-gonet
Copy link
Member

One question though - should we do that by default?

@robertherber
Copy link
Contributor Author

robertherber commented Nov 3, 2020

One question though - should we do that by default?

Good point. I've made it configurable and opt-in (through the property iosEnableTouchpadTwoFingerGesture) for the PanGestureHandler as well as the Swipeable and DrawerLayout components. I added types and docs as well as applied it to the examples where it makes sense.

Copy link
Member

@jakub-gonet jakub-gonet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some inline comments.

DrawerLayout.d.ts Outdated Show resolved Hide resolved
DrawerLayout.js Outdated Show resolved Hide resolved
ios/Handlers/RNPanHandler.m Outdated Show resolved Hide resolved
@jakub-gonet
Copy link
Member

I pasted some test code into a description. I don't have access to the touchpad connected to the iPad, you please verify that it works with this PR?

@robertherber
Copy link
Contributor Author

@jakub-gonet I've verified that the test code works - and of course the examples. Ready to merge?

Copy link
Member

@jakub-gonet jakub-gonet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGMT, thanks for the patch.

@jakub-gonet jakub-gonet changed the title Touchpad scrolling on iPadOS Allow two finger touchpad scrolling on iPadOS Nov 14, 2020
@jakub-gonet jakub-gonet merged commit b8f0c8e into software-mansion:master Nov 14, 2020
@robertherber robertherber deleted the touchpad-scrolling branch November 15, 2020 16:06
braincore pushed a commit to braincore/react-native-gesture-handler that referenced this pull request Mar 4, 2021
## Description

Adding support for touchpad in PanGestureHandler by setting `allowedScrollTypesMask` to `UIScrollTypeMaskAll` for  all devices with iOS 13.4+. Important for iPads with Touchpads and should work with Mac Catalyst through the same API as well. As described in software-mansion#1100 - this covers the ipadOS part of that issue.

## Test plan

Run on an iPad with touchpad. It's now possible to two-finger swipe to interact with the PanGestureHandler.

```jsx
import React from 'react';
import { AppRegistry, SafeAreaView, Animated } from 'react-native';
import { PanGestureHandler, State } from 'react-native-gesture-handler';

const Example = () => {
  const translateX = new Animated.Value(0);
  const translateY = new Animated.Value(0);
  const lastOffset = { x: 0, y: 0 };

  const onPanGestureEvent = Animated.event([
    {
      nativeEvent: {
        translationX: translateX,
        translationY: translateY,
      },
    },
  ]);

  const onHandlerStateChange = ({
    nativeEvent: { translationX, translationY, oldState },
  }) => {
    if (oldState === State.ACTIVE) {
      // compensate a start of pan
      lastOffset.x += translationX;
      lastOffset.y += translationY;
      translateX.setOffset(lastOffset.x);
      translateY.setOffset(lastOffset.y);

      translateX.setValue(0);
      translateY.setValue(0);
    }
  };

  return (
    <SafeAreaView style={styles.container}>
      <PanGestureHandler
        onGestureEvent={onPanGestureEvent}
        onHandlerStateChange={onHandlerStateChange}>
        <Animated.View
          style={[
            styles.rectangle,
            {
              transform: [{ translateX }, { translateY }],
            },
          ]}
        />
      </PanGestureHandler>
    </SafeAreaView>
  );
};

const styles = {
  container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
  rectangle: {
    backgroundColor: 'pink',
    width: 100,
    height: 100,
  },
};

AppRegistry.registerComponent('Example', () => Example);
```

Co-authored-by: Jakub Gonet <[email protected]>
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

Successfully merging this pull request may close these issues.

2 participants