在特定情况下,如果数据为空,如何防止滚动



我有两个顶部选项卡。每个选项卡都有一个从API、接收数据的组件

我已经通过添加动画将这些选项卡包装在滚动视图中,当您按下第二个选项卡时,组件会显示在屏幕上,并带有滑动动画。

但我有个问题。如果我在选项卡1中,并且选项卡的组件有一长串数据;在滚动到最后之后,如果我按下Tab 2,则滚动指示符也显示在Tab 2中,";在视图的末尾"!

那么,我可以让标签有单独的卷轴吗?

我在这里做了一个活生生的例子

尝试在选项卡中向下滚动"打开";。然后转到选项卡";闭合的";你会的查看问题

这是代码

import * as React from 'react';
import {
View,
Animated,
Text,
TouchableOpacity,
ScrollView,
StyleSheet,
FlatList,
Dimensions,
} from 'react-native';
const { width, height } = Dimensions.get('window');
const SPACING = 20;
const SLIDE_WIDTH = width - SPACING * 2;
export default function App() {
const [openedOrders, setOpenedOrders] = React.useState([]);
const [closedOrders, setClosedOrders] = React.useState([]);
const [active, setActive] = React.useState(0);
const [xTabOne, setXTabOne] = React.useState(0);
const [xTabTwo, setXTabTwo] = React.useState(0);
const [translateX] = React.useState(new Animated.Value(0));
const [translateXTabOne] = React.useState(new Animated.Value(0));
const [translateXTabTwo] = React.useState(new Animated.Value(width));
const [translateY, setTranslateY] = React.useState(-1000);
const handleSlide = React.useCallback(
(type) => {
Animated.spring(translateX, {
toValue: type,
duration: 100,
useNativeDriver: true,
}).start();
if (active === 0) {
Animated.parallel([
Animated.spring(translateXTabOne, {
toValue: 0,
duration: 100,
useNativeDriver: true,
}).start(),
Animated.spring(translateXTabTwo, {
toValue: width,
duration: 100,
useNativeDriver: true,
}).start(),
]);
} else {
Animated.parallel([
Animated.spring(translateXTabOne, {
toValue: width,
duration: 100,
useNativeDriver: true,
}).start(),
Animated.spring(translateXTabTwo, {
toValue: 0,
duration: 100,
useNativeDriver: true,
}).start(),
]);
}
},
[active, translateXTabOne, translateX, translateXTabTwo]
);
React.useEffect(() => {
active === 0 ? handleSlide(xTabTwo) : handleSlide(xTabOne);
}, [active, handleSlide, xTabTwo, xTabOne]);
return (
<>
<View
style={{
flexDirection: 'row',
marginTop: 20,
marginBottom: 20,
position: 'relative',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 15,
height: 61,
backgroundColor: '#ccc',
}}>
<Animated.View
style={{
position: 'absolute',
width: '50%',
height: '100%',
top: 0,
left: 0,
backgroundColor: '#000',
borderRadius: 15,
transform: [
{
translateX,
},
],
}}
/>
<TouchableOpacity
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
height: 61,
}}
onLayout={(event) => setXTabOne(event.nativeEvent.layout.x)}
onPress={() => {
setActive(1);
}}>
<Text
style={{
fontSize: 18,
color: active === 0 ? '#262626' : '#fff',
}}>
opened
</Text>
</TouchableOpacity>
<TouchableOpacity
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
height: 61,
}}
onLayout={(event) => setXTabTwo(event.nativeEvent.layout.x)}
onPress={() => {
setActive(0);
}}>
<Text
style={{
fontSize: 18,
color: active === 1 ? '#262626' : '#fff',
}}>
closed
</Text>
</TouchableOpacity>
</View>
<ScrollView
showsVerticalScrollIndicator={true}
// contentContainerStyle={{flexGrow: 1}}
>
<Animated.View
style={{
transform: [
{
translateX: translateXTabOne,
},
],
}}
onLayout={(event) => setTranslateY(event.nativeEvent.layout.height)}>
<FlatList
data={
[]
// Array(900).fill(0)
}
contentContainerStyle={{flexGrow:1}}
ListEmptyComponent={() => {
return (
<View style={{ flex: 1, backgroundColor: '#999' }}>
<Text>No data here...</Text>
</View>
);
}}
renderItem={({ item, index }) => {
return <Text key={index}>hey: {index}</Text>;
}}
keyExtractor={(item) => item.toString()}
/>
</Animated.View>
<Animated.View
style={{
transform: [
{
translateX: translateXTabTwo,
},
{
translateY: -translateY,
},
],
}}>
<FlatList
data={Array(900).fill(0)}
renderItem={({ item, index }) => {
return <Text key={index}>hey: {index}</Text>;
}}
keyExtractor={(item) => item.toString()}
/>
</Animated.View>
</ScrollView>
</>
);
}

我不能完全计算出你想要什么,但看起来你想要两个平面列表并排。

第一步是让他们并排。我们将制作一个容器视图,测量其宽度,在其中有第二个容器视图进行转换,然后在第二个集装箱视图中,我们将放置两个平面列表。

const Example = () => {
const [active, setActive] = React.useState(0)
const [width, setWidth] = React.useState(0)
const [translateX] = React.useState(() => new Animated.Value(0))
React.useLayoutEffect(() => {
Animated.timing(translateX, {
toValue: active * width,
duration: 300,
useNativeDriver: true
}).start()
}, [active, width, translateX])
return (
<View
style={{flex: 1}}
onLayout={e => setWidth(e.nativeEvent.layout.width)}
>
<Animated.View style={{flexDirection: 'row', transform: [{translateX}]}}>
<FlatList style={{width: width}} {…flatlist1Props} />
<FlatList style={{width: width}} {…flatlist2Props} />
</Animated.View>
</View>
)
}

现在,当您更改活动选项卡时,它将自动滑动到右侧列表。

如果您只想使用选项卡在列表之间切换,则不需要额外的ScrollView。

有一个名为React Navigation v5 的库

它为使用动画创建"顶部"选项卡提供了一个简单的解决方案。

与其自己创建选项卡并添加动画,我建议您使用该库来创建顶部选项卡。

它提供了一个非常干净的解决方案,您可以为每个选项卡创建两个单独的组件,并将它们添加到相应的选项卡中。

组件的内容和逻辑不会相互干扰。

这样,您就不必在ScrollView中嵌套FlatList了。

一定要考虑使用图书馆。它为React Native Apps中的导航提供了一些很棒的解决方案。

这将解决您目前在当前实施中面临的大多数问题。

以下是一些Youtube视频,演示如何使用React Navigation v5:

https://www.youtube.com/watch?v=nQVCkqvU1uE

https://www.youtube.com/watch?v=9KVJhOYOn1g

p.s:第一个视频在内容和解释上都要好得多。

最新更新