react-native-drag-sortというライブラリを使いました。 パッケージとしては改善の余地がありそうですが、ソースを見るとPanResnponderの使い方など参考になりそうです。
GitHub - mochixuan/react-native-drag-sort: 🔥🔥🔥Drag and drop sort control for react-native
const numOfImage = 5; const window = Dimensions.get('window'); const childrenWidth = 76; const childrenHeight = 76; const RegisterScreen = ({ navigation }) => { let [data, setData] = React.useState([]); let [isScrollEnabled, setScrollEnabled] = React.useState(true); let [parentWidth, setParentWidth] = React.useState(0); React.useEffect(() => { let newdata = [ // { image: 'test.png' }, // { image: 'test.png' }, // { image: 'test.png' }, ]; setData(newdata); setParentWidth(childrenWidth * newdata.length); }, []); const AddImageNew = () => { addData = () => { let newdata = [...data]; newdata.push({ image: 'test.png' }); setData(newdata); setParentWidth(childrenWidth * newdata.length); }; return ( <TouchableOpacity style={{ ...styles.imageBox, backgroundColor: 'tomato', }} onPress={addData} > <Icon type="antdesign" name="plus" color="white" size={32} /> </TouchableOpacity> ); }; const AddImageEmpty = () => { return ( <TouchableOpacity style={{ ...styles.imageBox, backgroundColor: 'grey', }} ></TouchableOpacity> ); }; const AddImageDone = () => { return ( <TouchableOpacity style={{ ...styles.imageBox, }} > </TouchableOpacity> ); }; renderItem = (item, index) => { return ( <View style={{ ...styles.imageBox, }} > {/* <Image></Image> */} </View> ); }; renderEmptyBox = () => { let count = numOfImage - data.length; let render = []; for (let i = 0; i < count; i++) { if (i == 0) { render.push(<AddImageNew key={i.toString()} data={data} />); } else { render.push(<AddImageEmpty key={i.toString()} />); } } return <>{render}</>; }; return ( <SafeAreaView style={styles.container}> <ScrollView> <View style={{ height: 110 }}> <Text>画像</Text> <ScrollView horizontal scrollEnabled={isScrollEnabled}> <View style={{ flex: 1, flexDirection: 'row', }} > {parentWidth >= childrenWidth && ( <DragSortableView dataSource={data} parentWidth={parentWidth} childrenWidth={childrenWidth} childrenHeight={childrenHeight} marginChildrenTop={0} marginChildrenBottom={0} marginChildrenLeft={0} marginChildrenRight={0} keyExtractor={(item, index) => index.toString()} renderItem={(item, index) => { return renderItem(item, index); }} onClickItem={(data, item, index) => { alert(item.image); }} onDataChange={(data) => {}} onDragStart={(startIndex, endIndex) => { setScrollEnabled(false); }} onDragEnd={(startIndex) => { setScrollEnabled(true); }} /> )} {renderEmptyBox()} </View> </ScrollView> </View> </ScrollView> </SafeAreaView> ); };