Javascript 在特定情况下,如果数据为空,如何防止滚动?
我有两个最上面的标签。每个选项卡都有一个从API接收数据的组件 我通过添加动画将这些选项卡包装在滚动视图中, 当按下第二个选项卡时,该组件将显示在屏幕上,并显示滑动动画 但我有个问题。如果我在选项卡1中,并且该选项卡的组件有一个很长的数据列表;滚动到末尾后,如果我按Tab 2,滚动指示器也会显示在Tab 2中,“在视图末尾” 那么,我可以让标签有单独的卷轴吗 我做了一个活生生的例子 尝试在“已打开”选项卡中向下滚动。然后转到“已关闭”选项卡,您将 看到问题了吗 这是密码Javascript 在特定情况下,如果数据为空,如何防止滚动?,javascript,reactjs,react-native,Javascript,Reactjs,React Native,我有两个最上面的标签。每个选项卡都有一个从API接收数据的组件 我通过添加动画将这些选项卡包装在滚动视图中, 当按下第二个选项卡时,该组件将显示在屏幕上,并显示滑动动画 但我有个问题。如果我在选项卡1中,并且该选项卡的组件有一个很长的数据列表;滚动到末尾后,如果我按Tab 2,滚动指示器也会显示在Tab 2中,“在视图末尾” 那么,我可以让标签有单独的卷轴吗 我做了一个活生生的例子 尝试在“已打开”选项卡中向下滚动。然后转到“已关闭”选项卡,您将 看到问题了吗 这是密码 import * as
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>
</>
);
}
import*as React from'React';
进口{
看法
有生气的
文本
可触摸不透明度,
滚动视图,
样式表,
平面列表,
尺寸,
}从“反应本机”;
const{width,height}=Dimensions.get('window');
常数间距=20;
常量滑动宽度=宽度-间距*2;
导出默认函数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(新的动画.Value(0));
const[translateXTabOne]=React.useState(新的动画.Value(0));
const[translateXTabTwo]=React.useState(新的动画.Value(width));
const[translateY,setTranslateY]=React.useState(-1000);
const handleSlide=React.useCallback(
(类型)=>{
动画。春天(translateX{
toValue:type,
持续时间:100,
useNativeDriver:没错,
}).start();
如果(活动===0){
平行动画([
动画。春天(translateXTabOne{
toValue:0,
持续时间:100,
useNativeDriver:没错,
}).start(),
动画。春天(第二{
toValue:width,
持续时间:100,
useNativeDriver:没错,
}).start(),
]);
}否则{
平行动画([
动画。春天(translateXTabOne{
toValue:width,
持续时间:100,
useNativeDriver:没错,
}).start(),
动画。春天(第二{
toValue:0,
持续时间:100,
useNativeDriver:没错,
}).start(),
]);
}
},
[活动,translateXTabOne,translateX,translateXTabTwo]
);
React.useffect(()=>{
活动===0?把手滑动(XTABTOW):把手滑动(xTabOne);
},[active,handleSlide,xTabTwo,xTabOne];
返回(
setXTabOne(event.nativeEvent.layout.x)}
onPress={()=>{
setActive(1);
}}>
开的
setXTabTwo(event.nativeEvent.layout.x)}
onPress={()=>{
setActive(0);
}}>
关闭
setTranslateY(event.nativeEvent.layout.height)}>
{
返回(
这里没有数据。。。
);
}}
renderItem={({item,index})=>{
返回hey:{index};
}}
keyExtractor={(item)=>item.toString()}
/>
{
返回hey:{index};
}}
keyExtractor={(item)=>item.toString()}
/>
);
}
有一个名为
它为创建动画提供了一个简单的解决方案
我建议您使用该库来创建顶部选项卡,而不是自己创建选项卡并添加动画
它提供了一个非常干净的解决方案,您可以为每个选项卡创建两个单独的组件,并将它们添加到相应的选项卡中
组件的内容和逻辑不会相互干扰
这样,您就不必在ScrollView中嵌套FlatList
一定要考虑使用图书馆。它为本地应用程序中的导航提供了一些很好的解决方案
这将解决当前实现中当前面临的大多数问题
以下是一些Youtube视频,演示如何使用React Navigation v5:
p、 s:从内容和解释上看,第一个视频要好得多。我不能完全理解你想要什么,但看起来你想要两个并排的平面列表 第一步是让他们肩并肩。我们将创建一个容器视图,测量它的宽度,在其中有一个我们转换的第二个容器视图,然后在第二个容器视图中,我们将放置两个平面列表
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>
)
}
const示例=()=>{
常量[active,setActive]=React.useState(0)
常量[width,setWidth]=React.useState(0)
const[translateX]=React.useState(()=>新的动画.Value(0))
React.useLayoutEffect(()=>{
动画。计时(translateX{
toValue:活动*宽度,
持续时间:300,
useNativeDriver:真的吗
}).start()
},[active,width,translateX])
返回(
setWidth(e.nativeEvent.layout.width)}
>
)
}
现在,当您更改活动选项卡时,它将自动滑到右侧列表
如果您只想使用选项卡在列表之间切换,则不需要额外的滚动视图。嘿,感谢您分享此信息,我已经在我的应用程序中使用RN v5,但整个问题,我不知道如何将
createMaterialTopTabNavigator
作为一个独立组件,在我的屏幕上使用它,就像这样//createMaterialTopTabNavigator
嗯,我只是在导航文件中导出一个常量TopTabs
,然后在任何屏幕中导入它,它工作得很好:“但是