我正在尝试实现2列中的可滚动卡片列表。卡片应该是可刷的左或右的屏幕外,以被删除。
基本上,这应该像Chrome应用程序当前显示标签列表的方式一样,这些选项卡可以被滑动关闭。参见示例图像这里。
我可以使用FlatList实现2列的卡片列表。不过,我在刷卡方面有困难.我尝试了反应-火药卡,但它不能限制刷卡上下,因此列表变得不可滚动。反应-本机甲板-刷卡也不能很好地与列表。
任何帮助都是非常感谢的。谢谢!
发布于 2022-03-06 20:14:16
我将实现满足以下要求的组件:
FlatList,其项目是您的卡。swipeLeft和swipeRight操作,这将删除刷卡。swipe动作应该是动画的,这意味着我们有某种drag of the screen行为。我将使用基本的react-带有numColumns={2}和反应-本机-滑动-列表-视图的本机numColumns={2}和反应-本机-滑动-列表-视图来处理swipeLeft和swipeRight动作以及所需的动画。
我将实现一个fire and forget操作,因此在删除一个项之后,它就永远消失了。如果希望能够还原已删除的项,稍后我们将实现restore mechanism。
我的初步实现工作如下:
FlatList的numColumns={2}和一些附加的虚拟样式,以添加一些空白。useState创建状态,它包含一个表示我们卡的对象数组。SwipeRow中呈现的项包装起来。removeItem函数传递给swipeGestureEnded支柱。import React, { useState } from "react"
import { FlatList, SafeAreaView, Text, View } from "react-native"
import { SwipeRow } from "react-native-swipe-list-view"
const data = [
{
id: "0",
title: "Title 1",
},
{
id: "1",
title: "Title 2",
},
{
id: "2",
title: "Title 3",
},
{
id: "3",
title: "Title 4",
},
{
id: "4",
title: "Title 5",
},
{
id: "5",
title: "Title 6",
},
{
id: "6",
title: "Title 7",
},
{
id: "7",
title: "Title 8",
},
]
export function Test() {
const [cards, setCards] = useState(data)
const [removed, setRemoved] = useState([])
function removeItem(id) {
let previous = [...cards]
let itemToRemove = previous.find((x) => x.id === id)
setCards(previous.filter((c) => c.id !== id))
setRemoved([...removed, itemToRemove])
}
return (
<SafeAreaView style={{ margin: 20 }}>
<FlatList
data={cards}
numColumns={2}
keyExtractor={(item) => item.id}
renderItem={({ index, item }) => (
<SwipeRow swipeGestureEnded={() => removeItem(item.id)}>
<View />
<View style={{ margin: 20, borderWidth: 1, padding: 20 }}>
<Text>{item.title}</Text>
</View>
</SwipeRow>
)}
/>
</SafeAreaView>
)
}注意,我们需要对象中的某种属性来确定要删除哪个属性。我在这里使用了一个基本的id属性,这在使用FlatList时很常见。如果您要从不提供相同API的id中检索数据,那么我们可以先做一些预处理(normalization),然后自己添加id支柱。
初始视图如下所示。

滑动,让我们假设‘标题6’的项目在右边或左边移除它。
也可能希望实现以下特性。
这很容易使用传递给renderItem函数的index参数和传递给swipeGestureEnded函数的gestureState的vx支柱来实现。
这是充分发挥作用的实施。
import React, { useState } from "react"
import { FlatList, SafeAreaView, Text, View } from "react-native"
import { SwipeRow } from "react-native-swipe-list-view"
const data = [
{
id: "0",
title: "Title 1",
},
{
id: "1",
title: "Title 2",
},
{
id: "2",
title: "Title 3",
},
{
id: "3",
title: "Title 4",
},
{
id: "4",
title: "Title 5",
},
{
id: "5",
title: "Title 6",
},
{
id: "6",
title: "Title 7",
},
{
id: "7",
title: "Title 8",
},
]
export function Test() {
const [cards, setCards] = useState(data)
const [removed, setRemoved] = useState([])
function removeItem(id) {
let previous = [...cards]
let itemToRemove = previous.find((x) => x.id === id)
setCards(previous.filter((c) => c.id !== id))
setRemoved([...removed, itemToRemove])
}
return (
<SafeAreaView style={{ margin: 20 }}>
<FlatList
data={cards}
numColumns={2}
keyExtractor={(item) => item.id}
renderItem={({ index, item }) => (
<SwipeRow
swipeGestureEnded={(key, event) => {
if (event.gestureState.vx < 0) {
if (index % 2 === 0) {
removeItem(item.id)
}
} else if (event.gestureState.vx >= 0) {
if (index % 2 === 1) {
removeItem(item.id)
}
}
}}
disableLeftSwipe={index % 2 === 1}
disableRightSwipe={index % 2 === 0}>
<View />
<View style={{ margin: 20, borderWidth: 1, padding: 20 }}>
<Text>{item.title}</Text>
</View>
</SwipeRow>
)}
/>
</SafeAreaView>
)
}由于索引在FlatList中是零的,所以一个项在第二列中当且仅当index % 2 === 1 (例如,具有索引3的项总是在第二列中,因此不能被2整除),另一方面,一个项在第一列中当且仅当为index的index % 2 === 0可被2整除。
SwipeRowComponent中有几个回调函数道具,在某些情况下应该触发。然而,他们中的大多数没有在我的设置中工作,我仍然不知道为什么。我让它通过使用event.gestureState.vx属性来工作,如果我们向左滑动,它是负的,如果我们向右滑动,它是正的(包括零)。
我们可能希望实现一个undo按钮,因为它在这类功能中非常常见。这样做的办法如下:
Queue。然后,undo按钮只pops最后删除的项。下面是一个完全工作的实现,它使用一个虚拟的undo按钮来实现这一点。
import React, { useState } from "react"
import { Button, FlatList, SafeAreaView, Text, View } from "react-native"
import { SwipeRow } from "react-native-swipe-list-view"
const data = [
{
id: "0",
title: "Title 1",
},
{
id: "1",
title: "Title 2",
},
{
id: "2",
title: "Title 3",
},
{
id: "3",
title: "Title 4",
},
{
id: "4",
title: "Title 5",
},
{
id: "5",
title: "Title 6",
},
{
id: "6",
title: "Title 7",
},
{
id: "7",
title: "Title 8",
},
]
export function Test() {
const [cards, setCards] = useState(data)
const [removed, setRemoved] = useState([])
function removeItem(id) {
let previous = [...cards]
let itemToRemove = previous.find((x) => x.id === id)
setCards(previous.filter((c) => c.id !== id))
setRemoved([...removed, itemToRemove])
}
function undoRemove() {
if (removed && removed.length > 0) {
let itemToUndo = removed[removed.length - 1]
setCards([...cards, itemToUndo])
setRemoved(removed.filter((c) => c.id !== itemToUndo.id))
}
}
return (
<SafeAreaView style={{ margin: 20 }}>
<FlatList
data={cards}
numColumns={2}
keyExtractor={(item) => item.id}
renderItem={({ index, item }) => (
<SwipeRow
swipeGestureEnded={(key, event) => {
if (event.gestureState.vx < 0) {
if (index % 2 === 0) {
removeItem(item.id)
}
} else if (event.gestureState.vx >= 0) {
if (index % 2 === 1) {
removeItem(item.id)
}
}
}}
disableLeftSwipe={index % 2 === 1}
disableRightSwipe={index % 2 === 0}>
<View />
<View style={{ margin: 20, borderWidth: 1, padding: 20 }}>
<Text>{item.title}</Text>
</View>
</SwipeRow>
)}
/>
<Button onPress={undoRemove} title="Undo" />
</SafeAreaView>
)
}注意,我的undo按钮只是将删除的项附加到列表的末尾。如果要保留初始索引,则需要保存旧索引并将项目推送到正确位置。
下面是我最后一个实现的工作中的小吃。
https://stackoverflow.com/questions/71268248
复制相似问题