Skip to content

Instantly share code, notes, and snippets.

@quarrant
Last active October 17, 2022 12:17
Show Gist options
  • Save quarrant/058f486ba0bcf78543f9bcdece486a73 to your computer and use it in GitHub Desktop.
Save quarrant/058f486ba0bcf78543f9bcdece486a73 to your computer and use it in GitHub Desktop.
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}
/>
)
}
};
@quarrant
Copy link
Author

quarrant commented Dec 13, 2018

<InteractableFlatList 
    keyExtractor={item => item.id.toString()}
    renderItem={item => <Text>{item.text}</Text>}                
    data={data}
    onPress={(item)=>{}}
    rightSideWidth={200}
    rightButtons={[
        <Button>Button 1</Button>,
        <Button>Button 2</Button>
    ]}
/>

leftSideWidth - расстояние на которое возможен свайп левой стороны. Ширина кнопок вписывается в это значение.

leftSideWidth={200}

leftButtons - массив, содержащий перечисление всех кнопок с левой стороны.

leftButtons={[
  <Button>button 1</Button>,
  <Button>button 2</Button>
]}

rightSideWidth - расстояние на которое возможен свайп правой стороны. Ширина кнопок вписывается в это значение.

rightSideWidth={200}

rightButtons - массив, содержащий перечисление всех кнопок с правой стороны.

rightButtons={[
  <Button>button 1</Button>,
  <Button>button 2</Button>
]}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment