-
Notifications
You must be signed in to change notification settings - Fork 734
Feat/with scroll enabler #807
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
Changes from 9 commits
9c03811
0c26378
4bf7b85
b7004b7
7da3d1d
529d258
fbb5305
7023e0b
25126ef
8e5a637
40a13d0
a7602ef
bd74f12
8efb178
3ab273b
01fe4f4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import _ from 'lodash'; | ||
import React, {memo} from 'react'; | ||
import { | ||
FlatList, | ||
FlatListProps, | ||
StyleSheet, | ||
LayoutChangeEvent | ||
} from 'react-native'; | ||
import memoize from 'memoize-one'; | ||
import { | ||
Colors, | ||
Text, | ||
View, | ||
withScrollEnabler, | ||
WithScrollEnablerProps | ||
} from 'react-native-ui-lib'; | ||
|
||
export type AutoLockScrollViewProps = FlatListProps<number> & { | ||
numberOfItems: number; | ||
}; | ||
|
||
const AutoLockFlatList = (props: AutoLockScrollViewProps) => { | ||
const numberOfItems = props.numberOfItems; | ||
|
||
const WithScrollEnabler = withScrollEnabler( | ||
(props: WithScrollEnablerProps) => { | ||
const getData = memoize((numberOfItems: number) => { | ||
return [...Array(numberOfItems).keys()]; | ||
}); | ||
|
||
function keyExtractor(item: number) { | ||
return item.toString(); | ||
} | ||
function renderItem({index}: {index: number}) { | ||
return ( | ||
<View key={index} style={styles.item}> | ||
<Text>{index + 1}</Text> | ||
</View> | ||
); | ||
} | ||
|
||
function onContentSizeChange( | ||
contentWidth: number, | ||
contentHeight: number | ||
) { | ||
_.invoke(props, 'onContentSizeChange', contentWidth, contentHeight); | ||
_.invoke( | ||
props, | ||
'scrollEnablerProps.onContentSizeChange', | ||
contentWidth, | ||
contentHeight | ||
); | ||
} | ||
|
||
function onLayout(nativeEvent: LayoutChangeEvent) { | ||
_.invoke(props, 'onLayout', nativeEvent); | ||
_.invoke(props, 'scrollEnablerProps.onLayout', nativeEvent); | ||
} | ||
|
||
return ( | ||
<FlatList | ||
{...props} | ||
style={styles.flatList} | ||
contentContainerStyle={styles.flatListContainer} | ||
showsHorizontalScrollIndicator={false} | ||
showsVerticalScrollIndicator={false} | ||
data={getData(numberOfItems)} | ||
renderItem={renderItem} | ||
keyExtractor={keyExtractor} | ||
onContentSizeChange={onContentSizeChange} | ||
onLayout={onLayout} | ||
scrollEnabled={props.scrollEnablerProps.scrollEnabled} | ||
/> | ||
); | ||
} | ||
); | ||
|
||
return <WithScrollEnabler {...props} />; | ||
}; | ||
|
||
export default memo(AutoLockFlatList); | ||
|
||
const styles = StyleSheet.create({ | ||
flatList: { | ||
height: 240 | ||
}, | ||
flatListContainer: { | ||
alignItems: 'center' | ||
}, | ||
item: { | ||
width: 100, | ||
height: 100, | ||
margin: 9, | ||
backgroundColor: Colors.grey40, | ||
alignItems: 'center', | ||
justifyContent: 'center' | ||
} | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import _ from 'lodash'; | ||
import React, {memo} from 'react'; | ||
import { | ||
ScrollView, | ||
ScrollViewProps, | ||
StyleSheet, | ||
LayoutChangeEvent | ||
} from 'react-native'; | ||
import { | ||
Colors, | ||
Text, | ||
View, | ||
withScrollEnabler, | ||
WithScrollEnablerProps | ||
} from 'react-native-ui-lib'; | ||
|
||
export type AutoLockScrollViewProps = ScrollViewProps & { | ||
numberOfItems: number; | ||
}; | ||
|
||
const AutoLockScrollView = (props: AutoLockScrollViewProps) => { | ||
const numberOfItems = props.numberOfItems; | ||
|
||
const WithScrollEnabler = withScrollEnabler( | ||
(props: WithScrollEnablerProps) => { | ||
function renderItem(index: number) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You must use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed to useCallback |
||
return ( | ||
<View key={index} style={styles.item}> | ||
<Text>{index + 1}</Text> | ||
</View> | ||
); | ||
} | ||
|
||
function onContentSizeChange( | ||
contentWidth: number, | ||
contentHeight: number | ||
) { | ||
_.invoke(props, 'onContentSizeChange', contentWidth, contentHeight); | ||
_.invoke( | ||
props, | ||
'scrollEnablerProps.onContentSizeChange', | ||
contentWidth, | ||
contentHeight | ||
); | ||
} | ||
|
||
function onLayout(nativeEvent: LayoutChangeEvent) { | ||
_.invoke(props, 'onLayout', nativeEvent); | ||
_.invoke(props, 'scrollEnablerProps.onLayout', nativeEvent); | ||
} | ||
|
||
return ( | ||
<ScrollView | ||
{...props} | ||
style={styles.scrollView} | ||
contentContainerStyle={styles.scrollViewContainer} | ||
showsHorizontalScrollIndicator={false} | ||
showsVerticalScrollIndicator={false} | ||
onContentSizeChange={onContentSizeChange} | ||
onLayout={onLayout} | ||
scrollEnabled={props.scrollEnablerProps.scrollEnabled} | ||
> | ||
{_.times(numberOfItems, renderItem)} | ||
</ScrollView> | ||
); | ||
} | ||
); | ||
|
||
return <WithScrollEnabler {...props} />; | ||
}; | ||
|
||
export default memo(AutoLockScrollView); | ||
|
||
const styles = StyleSheet.create({ | ||
scrollView: { | ||
height: 240 | ||
}, | ||
scrollViewContainer: { | ||
alignItems: 'center' | ||
}, | ||
item: { | ||
width: 100, | ||
height: 100, | ||
margin: 9, | ||
backgroundColor: Colors.grey40, | ||
alignItems: 'center', | ||
justifyContent: 'center' | ||
} | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import React, {Component} from 'react'; | ||
import {LayoutChangeEvent} from 'react-native'; | ||
import {Text, View} from 'react-native-ui-lib'; | ||
import { | ||
renderHeader, | ||
renderBooleanOption, | ||
renderSliderOption | ||
} from '../../ExampleScreenPresenter'; | ||
import AutoLockScrollView from './AutoLockScrollView'; | ||
import AutoLockFlatList from './AutoLockFlatList'; | ||
|
||
class WithScrollEnablerScreen extends Component { | ||
state = { | ||
isListView: false, | ||
isHorizontal: false, | ||
numberOfItems: 3, | ||
contentWidth: undefined, | ||
contentHeight: undefined, | ||
layoutWidth: undefined, | ||
layoutHeight: undefined | ||
}; | ||
|
||
onContentSizeChange = (contentWidth: number, contentHeight: number) => { | ||
const { | ||
contentWidth: currentContentWidth, | ||
contentHeight: currentContentHeight | ||
} = this.state; | ||
if ( | ||
currentContentWidth !== contentWidth || | ||
currentContentHeight !== contentHeight | ||
) { | ||
this.setState({contentWidth, contentHeight}); | ||
} | ||
}; | ||
|
||
onLayout = ({ | ||
nativeEvent: { | ||
layout: {width, height} | ||
} | ||
}: LayoutChangeEvent) => { | ||
const {layoutWidth, layoutHeight} = this.state; | ||
if (width !== layoutWidth || height !== layoutHeight) { | ||
this.setState({layoutWidth: width, layoutHeight: height}); | ||
} | ||
}; | ||
|
||
renderList = () => { | ||
const {isListView, isHorizontal, numberOfItems} = this.state; | ||
const Container = isListView ? AutoLockScrollView : AutoLockFlatList; | ||
|
||
return ( | ||
// @ts-ignore | ||
<Container | ||
key={`${isHorizontal}`} | ||
horizontal={isHorizontal} | ||
numberOfItems={numberOfItems} | ||
onContentSizeChange={this.onContentSizeChange} | ||
onLayout={this.onLayout} | ||
/> | ||
); | ||
}; | ||
|
||
renderData = () => { | ||
const {contentWidth, contentHeight, layoutWidth, layoutHeight} = this.state; | ||
const contentText = `Content {width, height}: ${contentWidth}, ${contentHeight}`; | ||
const layoutText = `Layout {width, height}: ${layoutWidth}, ${layoutHeight}`; | ||
return ( | ||
<> | ||
<Text text70>{contentText}</Text> | ||
<Text text70>{layoutText}</Text> | ||
</> | ||
); | ||
}; | ||
|
||
renderOptions = () => { | ||
const {isListView, isHorizontal} = this.state; | ||
const orientationText = isHorizontal ? 'Horizontal' : 'Vertical'; | ||
const listTypeText = isListView ? 'ListView' : 'FlatList'; | ||
return ( | ||
<> | ||
<View row> | ||
<View flex marginR-10> | ||
{renderBooleanOption.call(this, orientationText, 'isHorizontal')} | ||
</View> | ||
<View flex marginL-10> | ||
{renderBooleanOption.call(this, listTypeText, 'isListView')} | ||
</View> | ||
</View> | ||
{renderSliderOption.call( | ||
this, | ||
'Number of items shown', | ||
'numberOfItems', | ||
{ | ||
min: 1, | ||
max: 5, | ||
step: 1, | ||
initial: 3 | ||
} | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
render() { | ||
return ( | ||
<View margin-10> | ||
{renderHeader('withScrollEnabler', {'marginB-10': true})} | ||
{this.renderOptions()} | ||
{this.renderData()} | ||
{this.renderList()} | ||
</View> | ||
); | ||
} | ||
} | ||
|
||
export default WithScrollEnablerScreen; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
export { default as UIComponent } from './UIComponent'; | ||
export { default as asBaseComponent, BaseComponentInjectedProps } from './asBaseComponent'; | ||
export { default as forwardRef, ForwardRefInjectedProps } from './forwardRef'; | ||
export { default as withScrollEnabler } from './withScrollEnabler'; | ||
export { ContainerModifiers, MarginModifiers, TypographyModifiers, ColorsModifiers, BackgroundColorModifier } from './modifiers'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import React from 'react'; | ||
import { FlatListProps, ScrollViewProps, LayoutChangeEvent } from 'react-native'; | ||
export declare type ScrollEnablerProps = { | ||
onContentSizeChange: (contentWidth: number, contentHeight: number) => void; | ||
onLayout: (event: LayoutChangeEvent) => void; | ||
scrollEnabled: boolean; | ||
}; | ||
declare type SupportedViews = FlatListProps<any> | ScrollViewProps; | ||
export declare type WithScrollEnablerProps = SupportedViews & { | ||
scrollEnablerProps: ScrollEnablerProps; | ||
ref?: any; | ||
}; | ||
declare function withScrollEnabler<PROPS extends SupportedViews>(WrappedComponent: React.ComponentType<WithScrollEnablerProps>): React.ComponentType<PROPS>; | ||
export default withScrollEnabler; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
even though you memoize this function you still re-creating it on each render.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to useCallback