I am trying to achieve selection of multiple elements of an array by PanResponder. It works with horizontal or vertical touching sequence but I can't make it to work with diagonal. When I say diagonal, it selects all elements next to the touched elements of the array but I want to keep only the touched ones. For example I only need 1, 7 and 13. How can I achieve this?
The code is as follows
import React, {useState, useEffect, useRef} from 'react';
import {
View,Dimensions,
Text,
StyleSheet,
TouchableOpacity,
PanResponder,
PanResponderGestureState,
SafeAreaView,
LayoutChangeEvent,
} from 'react-native';
const SQUARE_SIZE = Dimensions.get("window").width/5;
const squareList = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27,
];
type OffsetType = {
id: number;
x: number;
y: number;
height: number;
width: number;
};
export default function App() {
const [selectedList, setSelectedList] = useState([]);
const [gestureSelectionList, setGestureSelectionList] = useState(
[],
);
const [offset, setOffset] = React.useState([]);
const [translate, setTranslate] = useState(
null,
);
console.log(
'offset',
offset.find(item => item.id === 2),
);
useEffect(() => {
console.log("ASDSA");
if (translate !== null) {
offset.map(offsetItem => {
const {moveX, moveY, x0, y0} = translate;
if (
(offsetItem.x >= x0 - SQUARE_SIZE &&
offsetItem.y >= y0 - SQUARE_SIZE &&
offsetItem.x <= moveX &&
offsetItem.y <= moveY)
) {
const isAlreadySelected = gestureSelectionList.find(
item => item === offsetItem.id,
);
if (!isAlreadySelected) {
setGestureSelectionList(prevState => [...prevState, offsetItem.id]);
}
} else {
const isAlreadySelected = gestureSelectionList.find(
item => item === offsetItem.id,
);
if (isAlreadySelected) {
const filterSelectedItem = gestureSelectionList.filter(
item => item !== offsetItem.id,
);
setGestureSelectionList(filterSelectedItem);
}
}
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [translate]);
const onSelectItem = (pressedItem: number) => {
const isAlreadySelected = selectedList.find(item => item === pressedItem);
if (isAlreadySelected) {
const filterSelectedItem = selectedList.filter(
item => item !== pressedItem,
);
setSelectedList(filterSelectedItem);
} else {
setSelectedList(prevState => [...prevState, pressedItem]);
}
};
function removeDuplicateAndMerge(
selectedArray: number[],
gestureSelectedArray: number[],
): number[] {
const myArray = selectedArray.filter(function (el) {
return gestureSelectedArray.indexOf(el) < 0;
});
const revArray = gestureSelectedArray.filter(function (el) {
return selectedArray.indexOf(el) < 0;
});
return [...myArray, ...revArray];
}
useEffect(() => {
if (!translate) {
setSelectedList(
removeDuplicateAndMerge(selectedList, gestureSelectionList),
);
setGestureSelectionList([]);
}
}, [translate]);
const panResponder = useRef(
PanResponder.create({
onMoveShouldSetPanResponder: () => true,
onMoveShouldSetPanResponderCapture: _evt => true,
onPanResponderMove: (_evt, gesture) => {
setTranslate({...gesture});
},
onPanResponderRelease: () => {
setTranslate(null);
},
onShouldBlockNativeResponder: () => true,
}),
).current;
const itemStyle = (item: number) => {
const gestureBGColor = gestureSelectionList.find(
selectedItem => selectedItem === item,
)
? true
: false;
const selectedBGColor = selectedList.find(
selectedItem => selectedItem === item,
)
? true
: false;
return {
backgroundColor: gestureBGColor
? 'gray'
: selectedBGColor
? 'blue'
: 'orangered',
};
};
return (
<View style={styles.listWrapper} {...panResponder.panHandlers}>
{squareList.map(item => {
return (
<TouchableOpacity
onLayout={(event: LayoutChangeEvent | any) => {
event.target.measure(
(
_x: number,
_y: number,
width: number,
height: number,
pageX: number,
pageY: number,
) => {
setOffset(prevOffset => [
...prevOffset,
{
id: item,
x: pageX,
y: pageY,
width,
height,
},
]);
},
);
}}
onPress={() => onSelectItem(item)}
key={item}
style={[styles.squareStyle, itemStyle(item)]}>
<Text style={{color: '#fff', fontSize: 18}}>{item}</Text>
</TouchableOpacity>
);
})}
</View>
);
}
const styles = StyleSheet.create({
listWrapper: {
flexDirection: 'row',
flexWrap: 'wrap',
},
squareStyle: {
backgroundColor: 'orangered',
height: SQUARE_SIZE,
width: SQUARE_SIZE,
borderWidth:1,
justifyContent: 'center',
alignItems: 'center',
},
});