diff --git a/src/components/TextInput/TextInput.tsx b/src/components/TextInput/TextInput.tsx index 1bdd7cef00..b97d398e4b 100644 --- a/src/components/TextInput/TextInput.tsx +++ b/src/components/TextInput/TextInput.tsx @@ -172,6 +172,11 @@ export type Props = React.ComponentPropsWithRef & { * Example: `borderRadius`, `borderColor` */ underlineStyle?: StyleProp; + /** + * Pass true to disable input focus on scroll. + * See: https://github.com/callstack/react-native-paper/issues/4666 + */ + disableFocusOnScroll?: boolean; }; interface CompoundedComponent @@ -223,7 +228,10 @@ const TextInput = forwardRef( error: errorProp = false, multiline = false, editable = true, + disableFocusOnScroll = false, contentStyle, + onScroll, + onTouchEnd, render = DefaultRenderer, theme: themeOverrides, ...rest @@ -280,6 +288,7 @@ const TextInput = forwardRef( width: null, height: null, }); + const [isScrolling, setScrolling] = React.useState(false); const timer = React.useRef(); @@ -403,6 +412,22 @@ const TextInput = forwardRef( [rightLayout.height, rightLayout.width] ); + const handleTouchEnd = (args: any) => { + if (disableFocusOnScroll) { + setScrolling(false); + } + // also handle component specific event + onTouchEnd?.(args); + }; + + const handleScroll = (args: any) => { + if (disableFocusOnScroll) { + setScrolling(true); + } + // also handle component specific event + onScroll?.(args); + }; + const handleFocus = (args: any) => { if (disabled || !editable) { return; @@ -484,7 +509,12 @@ const TextInput = forwardRef( disabled={disabled} error={errorProp} multiline={multiline} - editable={editable} + // if disabledFocusOnScroll is enabled + editable={ + (disableFocusOnScroll ? !isScrolling : undefined) || editable + } + onTouchEnd={handleTouchEnd} + onScroll={handleScroll} render={render} {...rest} theme={theme} @@ -526,8 +556,11 @@ const TextInput = forwardRef( disabled={disabled} error={errorProp} multiline={multiline} - editable={editable} render={render} + // if disabledFocusOnScroll is enabled + editable={(disableFocusOnScroll ? !isScrolling : undefined) || editable} + onTouchEnd={handleTouchEnd} + onScroll={handleScroll} {...rest} theme={theme} value={value} diff --git a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap index f57eb469b0..27f43a74fb 100644 --- a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -184,6 +184,8 @@ exports[`call onPress when affix adornment pressed 1`] = ` onBlur={[Function]} onChangeText={[Function]} onFocus={[Function]} + onScroll={[Function]} + onTouchEnd={[Function]} placeholder="Enter your phone number" placeholderTextColor="transparent" selectionColor="rgba(103, 80, 164, 1)" @@ -498,6 +500,8 @@ exports[`correctly applies a component as the text label 1`] = ` onBlur={[Function]} onChangeText={[Function]} onFocus={[Function]} + onScroll={[Function]} + onTouchEnd={[Function]} placeholder="Type something" placeholderTextColor="transparent" selectionColor="rgba(103, 80, 164, 1)" @@ -724,6 +728,8 @@ exports[`correctly applies cursorColor prop 1`] = ` onBlur={[Function]} onChangeText={[Function]} onFocus={[Function]} + onScroll={[Function]} + onTouchEnd={[Function]} placeholder="Type something" placeholderTextColor="transparent" selectionColor="rgba(103, 80, 164, 1)" @@ -950,6 +956,8 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` onBlur={[Function]} onChangeText={[Function]} onFocus={[Function]} + onScroll={[Function]} + onTouchEnd={[Function]} placeholder="Type something" placeholderTextColor="transparent" selectionColor="rgba(103, 80, 164, 1)" @@ -1208,6 +1216,8 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` onChangeText={[Function]} onFocus={[Function]} onLayout={[Function]} + onScroll={[Function]} + onTouchEnd={[Function]} placeholder="Type Something" placeholderTextColor="transparent" selectionColor="rgba(103, 80, 164, 1)" @@ -1435,6 +1445,8 @@ exports[`correctly applies paddingLeft from contentStyleProp 1`] = ` onBlur={[Function]} onChangeText={[Function]} onFocus={[Function]} + onScroll={[Function]} + onTouchEnd={[Function]} placeholder="Type something" placeholderTextColor="transparent" selectionColor="rgba(103, 80, 164, 1)" @@ -1663,6 +1675,8 @@ exports[`correctly applies textAlign center 1`] = ` onBlur={[Function]} onChangeText={[Function]} onFocus={[Function]} + onScroll={[Function]} + onTouchEnd={[Function]} placeholder="Type something" placeholderTextColor="transparent" selectionColor="rgba(103, 80, 164, 1)" @@ -1889,6 +1903,8 @@ exports[`correctly renders left-side affix adornment, and right-side icon adornm onBlur={[Function]} onChangeText={[Function]} onFocus={[Function]} + onScroll={[Function]} + onTouchEnd={[Function]} placeholder="Type something" placeholderTextColor="transparent" selectionColor="rgba(103, 80, 164, 1)" @@ -2315,6 +2331,8 @@ exports[`correctly renders left-side icon adornment, and right-side affix adornm onBlur={[Function]} onChangeText={[Function]} onFocus={[Function]} + onScroll={[Function]} + onTouchEnd={[Function]} placeholder="Type something" placeholderTextColor="transparent" selectionColor="rgba(103, 80, 164, 1)"