Last active
October 17, 2022 12:17
-
-
Save quarrant/058f486ba0bcf78543f9bcdece486a73 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import Interactable, { IDragEvent, INativeDragEvent } from 'react-native-interactable'; | |
import { StyleSheet, TouchableOpacity, View, FlatList, GestureResponderEvent } from 'react-native'; | |
export type InteractableListItemRefType = React.Component<Interactable.IInteractableView, {}, any> | null | undefined; | |
export interface ICommonProps { | |
onPress?: (event: GestureResponderEvent) => void | null, | |
rightButtons: Array<React.ReactElement<any>>, | |
leftButtons: Array<React.ReactElement<any>>, | |
rightSideWidth: number | 100, | |
leftSideWidth: number | 100, | |
}; | |
export interface IInteractableFlatListProps extends ICommonProps { | |
renderItem: (item: any) => React.ReactElement<any>, | |
keyExtractor: (item: any) => string, | |
initialNumToRender?: number | 10, | |
containerStyle?: object | {}, | |
inverted?: boolean | false, | |
extraData?: object | {}, | |
data: Array<any>, | |
}; | |
export interface IInteractableListItemProps extends ICommonProps { | |
onSwipeStart: (event: Interactable.INativeDragEvent, node: InteractableListItemRefType) => void, | |
onSwipeStop: (event: Interactable.INativeDragEvent, node: InteractableListItemRefType) => void, | |
}; | |
const styles = StyleSheet.create({ | |
container: { | |
flex: 1 | |
}, | |
buttons: { | |
position: 'absolute', | |
flexDirection: 'row', | |
height: 70 | |
} | |
}); | |
export default class InteractableRow extends React.Component<IInteractableListItemProps> { | |
private interactableRef: InteractableListItemRefType | |
private setInteractableRef = (ref: InteractableListItemRefType) => { | |
this.interactableRef = ref; | |
} | |
private onDrag = (event: IDragEvent) => { | |
const { onSwipeStart, onSwipeStop } = this.props; | |
if (event.nativeEvent.state === 'start') { | |
return onSwipeStart(event.nativeEvent, this.interactableRef); | |
} else if (event.nativeEvent.state === 'end') { | |
return onSwipeStop(event.nativeEvent, this.interactableRef); | |
}; | |
} | |
recenter = () => { | |
if (this.interactableRef) { | |
const localInteractableRef = this.interactableRef as any; | |
localInteractableRef.snapTo({ x: 0 }); | |
}; | |
} | |
render() { | |
const { | |
leftButtons, | |
leftSideWidth, | |
rightButtons, | |
rightSideWidth, | |
onPress, | |
children | |
} = this.props; | |
const leftButtonStyle = { | |
width: leftSideWidth, | |
left: 0 | |
}; | |
const rightButtonStyle = { | |
width: rightSideWidth, | |
right: 0 | |
}; | |
const snapPoints = [ | |
{ x: leftSideWidth }, | |
{ x: 0 }, | |
{ x: -rightSideWidth } | |
]; | |
const boundaries = { | |
right: leftSideWidth, | |
left: -rightSideWidth, | |
bounce: 0 | |
}; | |
const leftButtonsCollection = leftButtons.map((button: React.ReactElement<any>) => React.cloneElement(button)); | |
const rightButtonsCollection = rightButtons.map((button: React.ReactElement<any>) => React.cloneElement(button)); | |
return ( | |
<TouchableOpacity | |
style={styles.container} | |
activeOpacity={0.7} | |
onPress={onPress} | |
> | |
<View style={[styles.buttons, leftButtonStyle]}> | |
{leftButtonsCollection} | |
</View> | |
<View style={[styles.buttons, rightButtonStyle]}> | |
{rightButtonsCollection} | |
</View> | |
<Interactable.View | |
ref={this.setInteractableRef} | |
onDrag={this.onDrag} | |
horizontalOnly={true} | |
snapPoints={snapPoints} | |
boundaries={boundaries} | |
> | |
{children} | |
</Interactable.View> | |
</TouchableOpacity> | |
) | |
} | |
}; | |
export default class InteractableFlatList extends React.Component<IInteractableFlatListProps> { | |
private interactableRowRef: InteractableListItemRefType | |
interactableRowRecenter = () => { | |
if (this.interactableRowRef) { | |
const localInteractableRowRef = this.interactableRowRef as any; | |
localInteractableRowRef.recenter(); | |
}; | |
} | |
onSwipeStart = (event: INativeDragEvent, interactableRowRef: InteractableListItemRefType) => { | |
if (this.interactableRowRef && this.interactableRowRef !== interactableRowRef) { | |
this.interactableRowRecenter(); | |
}; | |
this.interactableRowRef = interactableRowRef; | |
} | |
onSwipeStop = (event: INativeDragEvent, interactableRowRef: InteractableListItemRefType) => { | |
// to do nothing | |
} | |
onScrollBeginDrag = () => { | |
if (this.interactableRowRef) { | |
this.interactableRowRecenter(); | |
}; | |
} | |
renderItem = (record: { item: object }) => { | |
const { | |
leftSideWidth, | |
rightSideWidth, | |
leftButtons, | |
rightButtons, | |
renderItem, | |
onPress, | |
} = this.props; | |
return ( | |
<InteractableRow | |
leftButtons={leftButtons} | |
rightButtons={rightButtons} | |
leftSideWidth={leftSideWidth} | |
rightSideWidth={rightSideWidth} | |
onSwipeStart={this.onSwipeStart} | |
onSwipeStop={this.onSwipeStop} | |
onPress={onPress} | |
> | |
{renderItem(record.item)} | |
</InteractableRow> | |
) | |
} | |
render() { | |
const { | |
initialNumToRender, | |
containerStyle, | |
keyExtractor, | |
extraData, | |
inverted, | |
data, | |
} = this.props; | |
return ( | |
<FlatList | |
style={[containerStyle]} | |
keyExtractor={keyExtractor} | |
onScrollBeginDrag={this.onScrollBeginDrag} | |
initialNumToRender={initialNumToRender} | |
renderItem={this.renderItem} | |
extraData={extraData} | |
inverted={inverted} | |
data={data} | |
/> | |
) | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
leftSideWidth
- расстояние на которое возможен свайп левой стороны. Ширина кнопок вписывается в это значение.leftButtons
- массив, содержащий перечисление всех кнопок с левой стороны.rightSideWidth
- расстояние на которое возможен свайп правой стороны. Ширина кнопок вписывается в это значение.rightButtons
- массив, содержащий перечисление всех кнопок с правой стороны.