[add] ScrollView support for pagingEnabled

Available in browsers that support CSS snappoints.

Fix #1057
Close #1212

Co-authored-by: Nicolas Gallagher <nicolasgallagher@gmail.com>
This commit is contained in:
krister
2018-12-22 14:12:31 -03:00
committed by Nicolas Gallagher
parent 2b77bfd853
commit 1e202b6bd5
6 changed files with 66 additions and 9 deletions

View File

@@ -140,7 +140,7 @@ React Native v0.55
| Picker | ✓ | |
| RefreshControl | ✘ | Not started ([#1027](https://github.com/necolas/react-native-web/issues/1027)). |
| SafeAreaView | ✓ | |
| ScrollView | ✓ | Missing momentum scroll events ([#1021](https://github.com/necolas/react-native-web/issues/1021)) and `pagingEnabled` ([#1057](https://github.com/necolas/react-native-web/issues/1057)). |
| ScrollView | ✓ | Missing momentum scroll events ([#1021](https://github.com/necolas/react-native-web/issues/1021)). |
| SectionList | ✓ | |
| Slider | ✘ | Not started ([#1022](https://github.com/necolas/react-native-web/issues/1022)). |
| StatusBar | (✓) | Mock. No equivalent web APIs. |

View File

@@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/ScrollView "pagingEnabled" prop 1`] = `undefined`;
exports[`components/ScrollView "pagingEnabled" prop 2`] = `"y mandatory"`;
exports[`components/ScrollView "pagingEnabled" prop 3`] = `"start"`;

View File

@@ -2,7 +2,8 @@
import React from 'react';
import ScrollView from '..';
import { mount } from 'enzyme';
import StyleSheet from '../../StyleSheet';
import { mount, shallow } from 'enzyme';
describe('components/ScrollView', () => {
test('instance method setNativeProps', () => {
@@ -11,4 +12,17 @@ describe('components/ScrollView', () => {
instance.setNativeProps();
}).not.toThrow();
});
test('"pagingEnabled" prop', () => {
const getStyleProp = (component, prop) => StyleSheet.flatten(component.prop('style'))[prop];
// false
const component = shallow(<ScrollView children={'Child'} />);
expect(getStyleProp(component, 'scrollSnapType')).toMatchSnapshot();
// true
component.setProps({ pagingEnabled: true });
expect(getStyleProp(component, 'scrollSnapType')).toMatchSnapshot();
expect(getStyleProp(component.children().childAt(0), 'scrollSnapAlign')).toMatchSnapshot();
});
});

View File

@@ -137,10 +137,10 @@ const ScrollView = createReactClass({
onContentSizeChange,
refreshControl,
stickyHeaderIndices,
pagingEnabled,
/* eslint-disable */
keyboardDismissMode,
onScroll,
pagingEnabled,
/* eslint-enable */
...other
} = this.props;
@@ -164,11 +164,24 @@ const ScrollView = createReactClass({
};
}
const hasStickyHeaderIndices = !horizontal && Array.isArray(stickyHeaderIndices);
const children =
!horizontal && Array.isArray(stickyHeaderIndices)
hasStickyHeaderIndices || pagingEnabled
? React.Children.map(this.props.children, (child, i) => {
if (child && stickyHeaderIndices.indexOf(i) > -1) {
return <View style={styles.stickyHeader}>{child}</View>;
if (child != null) {
const isSticky = hasStickyHeaderIndices && stickyHeaderIndices.indexOf(i) > -1;
if (isSticky || pagingEnabled) {
return (
<View
style={StyleSheet.compose(
isSticky && styles.stickyHeader,
pagingEnabled && styles.pagingEnabledChild
)}
>
{child}
</View>
);
}
} else {
return child;
}
@@ -181,15 +194,21 @@ const ScrollView = createReactClass({
children={children}
collapsable={false}
ref={this._setInnerViewRef}
style={[horizontal && styles.contentContainerHorizontal, contentContainerStyle]}
style={StyleSheet.compose(
horizontal && styles.contentContainerHorizontal,
contentContainerStyle
)}
/>
);
const baseStyle = horizontal ? styles.baseHorizontal : styles.baseVertical;
const pagingEnabledStyle = horizontal
? styles.pagingEnabledHorizontal
: styles.pagingEnabledVertical;
const props = {
...other,
style: [baseStyle, this.props.style],
style: [baseStyle, pagingEnabled && pagingEnabledStyle, this.props.style],
onTouchStart: this.scrollResponderHandleTouchStart,
onTouchMove: this.scrollResponderHandleTouchMove,
onTouchEnd: this.scrollResponderHandleTouchEnd,
@@ -223,7 +242,7 @@ const ScrollView = createReactClass({
}
return (
<ScrollViewClass {...props} ref={this._setScrollViewRef} style={props.style}>
<ScrollViewClass {...props} ref={this._setScrollViewRef}>
{contentContainer}
</ScrollViewClass>
);
@@ -294,6 +313,15 @@ const styles = StyleSheet.create({
position: 'sticky',
top: 0,
zIndex: 10
},
pagingEnabledHorizontal: {
scrollSnapType: 'x mandatory'
},
pagingEnabledVertical: {
scrollSnapType: 'y mandatory'
},
pagingEnabledChild: {
scrollSnapAlign: 'start'
}
});

View File

@@ -51,6 +51,8 @@ const ViewStylePropTypes = {
overscrollBehavior: overscrollBehaviorType,
overscrollBehaviorX: overscrollBehaviorType,
overscrollBehaviorY: overscrollBehaviorType,
scrollSnapAlign: string,
scrollSnapType: string,
WebkitMaskImage: string,
WebkitOverflowScrolling: oneOf(['auto', 'touch'])
};

View File

@@ -101,6 +101,12 @@ const ScrollViewScreen = () => (
]}
/>
<DocItem
name="pagingEnabled"
typeInfo="?boolean = false"
description="When true, the scroll view snaps to individual items in the list when scrolling."
/>
<DocItem
name="scrollEnabled"
typeInfo="?boolean = true"