Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"lodash.isequal": "^4.5.0"
},
"devDependencies": {
"@react-native-picker/picker": ">=2.1.0",
"@types/react-native": "^0.60.22",
"babel-jest": "^23.6.0",
"babel-preset-react-native": "^4.0.1",
Expand All @@ -43,7 +44,6 @@
"react": "16.6.1",
"react-dom": "^16.6.1",
"react-native": "0.57.7",
"@react-native-picker/picker": ">=2.1.0",
"react-test-renderer": "^16.6.1"
},
"peerDependencies": {
Expand Down
33 changes: 33 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import PropTypes from 'prop-types';
import isEqual from 'lodash.isequal';
import { Picker } from '@react-native-picker/picker';
import { defaultStyles } from './styles';
import { Dimensions } from 'react-native';

// Measuring the modal before rendering is not working reliably, so we need to hardcode the height
// This height was tested thoroughly on several iPhone Models (from iPhone 8 to 14 Pro)
const IOS_MODAL_HEIGHT = 262;
Copy link

Choose a reason for hiding this comment

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

How did you come up with a value of 262?

Copy link
Author

Choose a reason for hiding this comment

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

I tried to programatically measure the modal instead, but didn't succeed.

Instead i thoroughly tested this value on multiple iOS devices, since the height of the picker modal is the same on all (iOS) devices. Works the same way on iPhone 8:

Simulator.Screen.Recording.-.iPhone.8.-.2022-12-14.at.23.32.16.mp4

Copy link

Choose a reason for hiding this comment

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

OK, thanks! Can you please add that context as a code comment?


export default class RNPickerSelect extends PureComponent {
static propTypes = {
Expand Down Expand Up @@ -31,6 +36,8 @@ export default class RNPickerSelect extends PureComponent {
onOpen: PropTypes.func,
useNativeAndroidPickerStyle: PropTypes.bool,
fixAndroidTouchableBug: PropTypes.bool,
scrollViewRef: PropTypes.any,
scrollViewContentOffsetY: PropTypes.number,

// Custom Modal props (iOS only)
doneText: PropTypes.string,
Expand Down Expand Up @@ -137,6 +144,7 @@ export default class RNPickerSelect extends PureComponent {
this.onValueChange = this.onValueChange.bind(this);
this.onOrientationChange = this.onOrientationChange.bind(this);
this.setInputRef = this.setInputRef.bind(this);
this.scrollToInput = this.scrollToInput.bind(this);
this.togglePicker = this.togglePicker.bind(this);
this.renderInputAccessoryView = this.renderInputAccessoryView.bind(this);
}
Expand Down Expand Up @@ -214,12 +222,37 @@ export default class RNPickerSelect extends PureComponent {
return {};
}

scrollToInput() {
if (
this.props.scrollViewRef == null ||
this.props.scrollViewContentOffsetY == null ||
this.inputRef == null
) {
return;
}

this.inputRef.measureInWindow((_x, y, _width, height) => {
// Bottom y-position of TextInput on screen
const textInputBottomY = y + height;
// Top y-position of picker modal on screen
const modalY = Dimensions.get('window').height - IOS_MODAL_HEIGHT;

// If TextInput is below picker modal, scroll up
if (textInputBottomY > modalY) {
this.props.scrollViewRef.current.scrollTo({
y: textInputBottomY - modalY + this.props.scrollViewContentOffsetY,
});
}
});
}

triggerOpenCloseCallbacks() {
const { onOpen, onClose } = this.props;
const { showPicker } = this.state;

if (!showPicker && onOpen) {
onOpen();
this.scrollToInput();
}

if (showPicker && onClose) {
Expand Down