react-native-snap-carousel 无法正确呈现
react-native-snap-carousel doesn't render properly
问题总结
我正在使用 react-native-snap-carousel,但它没有正确呈现。它仅在被滑动后呈现,我需要在屏幕最初呈现时呈现。当我将屏幕分配给我的 BottomTabNavigator 的初始路线或在 React Navigation 中的 Stack Navigator 中的初始路线时,轮播会完美呈现。当我将完全相同的屏幕分配给 Stack Navigator 中的任何其他路线时,它不会呈现轮播,直到我滑动它。
我需要在我的 Stack Navigator 中使用带轮播的屏幕作为第二条路线,但我不知道如何让它正常工作。
我试过的
- 我试过将屏幕上的其他所有内容都去掉
- 我也试过从头开始创建一个新屏幕。
- 我已经在 Stack Navigator 中将屏幕作为初始路径进行了测试,并且
它工作得很好,但我仍然无法让旋转木马在
屏幕加载。
- 我也试过切换到基于 class 的 React 组件
没有帮助。
代码
带轮播的组件
import React, { useState } from "react";
import { View, Text } from "react-native";
import { useDispatch } from "react-redux";
import styles from "./StatSelectorStartComp.style";
import HeaderText from "~/app/Components/HeaderText/HeaderText";
import Carousel from "react-native-snap-carousel";
import LargeButton from "~/app/Components/Buttons/LargeButton/LargeButton";
import NavigationService from "~/app/services/NavigationService";
import { saveStartCompStatCategory } from "~/app/Redux/actions/dailyCompActions";
const StatSelectorStartComp = ({}) => {
const dispatch = useDispatch();
const ENTRIES1 = ["Kills", "Wins", "K/D", "Win %"];
const [selectedStat, setSelectedStat] = useState(ENTRIES1[0]);
const _renderItem = ({ item, index }) => {
return (
<View style={styles.slide}>
<Text style={styles.compSelectStatCarousel}>{item}</Text>
</View>
);
};
return (
<View style={styles.container}>
<View style={styles.headerTextView}>
<HeaderText header={"Configure Competition"} />
</View>
<Text style={styles.h5Secondary}> Which stat will you track?</Text>
<View style={styles.selectStatView}>
<Text style={styles.mediumGreyedOut}>Most {selectedStat} Wins</Text>
<Carousel
ref={c => {
_carousel = c;
}}
data={ENTRIES1}
renderItem={_renderItem}
sliderWidth={375}
itemWidth={100}
onSnapToItem={index => {
setSelectedStat(ENTRIES1[index]);
}}
/>
</View>
<View style={styles.buttonView}>
<LargeButton
onPress={() => {
dispatch(saveStartCompStatCategory(selectedStat));
NavigationService.navigate("CompAddFriends");
}}
buttonText="Add Friends"
/>
</View>
</View>
);
};
export default StatSelectorStartComp;
轮播组件的样式
import { StyleSheet } from "react-native";
import { backgroundColor } from "~/app/Constants";
import {
h5Secondary,
mediumGreyedOut,
compSelectStatCarousel
} from "~/app/FontConstants";
export default StyleSheet.create({
container: {
flex: 1,
justifyContent: "space-between",
backgroundColor
},
headerTextView: {
flex: 1
},
h5Secondary,
selectStatView: {
flex: 3
},
mediumGreyedOut,
compSelectStatCarousel,
buttonView: {
flex: 2
}
});
React 导航配置
const StartCompStack = createStackNavigator({
StartFriendsComp: {
screen: StartFriendsComp
},
StatSelectorStartComp: {
screen: CarouselTest
},
CompAddFriends: {
screen: CompAddFriends
},
FinalCompScreen: {
screen: FinalCompScreen
}
});
const ProfileStack = createStackNavigator({
Profile: {
screen: ProfileScreen
},
Settings: {
screen: SettingsScreen
}
});
const BottomTabNav = createBottomTabNavigator(
{
Home: {
screen: HomeScreen
},
Competitions: {
screen: Competitions
},
StartComp: {
screen: StartCompStack,
navigationOptions: () => ({
tabBarVisible: false
})
},
CompScreen: {
screen: CompScreen
},
Friends: {
screen: FriendsDrawer
},
Profile: {
screen: ProfileStack
},
FacebookFriendsList
},
{
tabBarComponent: CustomTabNav,
initialRouteName: "Home"
}
);
图片概括问题
加载屏幕时,轮播未呈现
在旋转木马上滑动后
我们的项目也遇到了同样的问题,一个小技巧可以帮助我们。我们已将默认加载状态设置为 true,并在 componentDidMount 中将状态设置为 false 以显示 Carousel
试试这个,它可能对你有帮助
state = { loading: true };
componentDidMount() {
setTimeout(() => {
this.setState({ loading: false });
}, 10);
}
render() {
if(this.state.loading) {
return null;
}
// return component render which contain Carousel
.........
}
<Carousel
ref={c => {
_carousel = c;
}}
data={ENTRIES1}
renderItem={_renderItem}
sliderWidth={375}
itemWidth={100}
onSnapToItem={index => {
setSelectedStat(ENTRIES1[index]);
}}
/>
</
我认为问题在于给出静态高度和宽度。尝试动态计算高度和宽度,然后显示它。这里的动态是指计算设备的高度和宽度,然后对其进行计算。
有一个实验性配置(当前为 v3.8.4)- removeClippedSubviews
- 默认设置为 true
。将其设置为 false
解决了我的问题。
我强烈建议不要使用延迟,因为它不是确定性的,并且会因设备而异。
感谢在评论中写下这篇文章的@auticcat。
我通过简单地使用 removeClippedSubviews={false}
解决了它
您可以创建自己的自定义轮播。 Carousel 最终结果如下所示-
goToNextPage = () => {
const childlenth = this.getCustomData().length;
selectedIndex = selectedIndex + 1;
this.clearTimer();
if (selectedIndex === childlenth) {
this.scrollRef.current.scrollTo({ offset: 0, animated: false, nofix: true });
selectedIndex = 1;
}
this.scrollRef.current.scrollTo({
animated: true,
x: this.props.childWidth * selectedIndex,
});
this.setUpTimer();
}
// pushing 1st element at last
getCustomData() {
const {data} = this.props;
const finaldata = [];
finaldata.push(...data);
finaldata.push(data[0]);
return finaldata;
}
这是循环轮播背后使用的主要逻辑。
在这里,我们再次推送列表中的第一个项目,然后当滚动到达最后一个位置时,我们让滚动视图滚动到第一个位置,因为现在第一个和最后一个元素相同,我们用这样的动画滚动到第一个位置
this.scrollRef.current.scrollTo({ offset: 0, animated: false, nofix: true });
如需进一步参考,请查看所提供的 link。
问题总结
我正在使用 react-native-snap-carousel,但它没有正确呈现。它仅在被滑动后呈现,我需要在屏幕最初呈现时呈现。当我将屏幕分配给我的 BottomTabNavigator 的初始路线或在 React Navigation 中的 Stack Navigator 中的初始路线时,轮播会完美呈现。当我将完全相同的屏幕分配给 Stack Navigator 中的任何其他路线时,它不会呈现轮播,直到我滑动它。
我需要在我的 Stack Navigator 中使用带轮播的屏幕作为第二条路线,但我不知道如何让它正常工作。
我试过的
- 我试过将屏幕上的其他所有内容都去掉
- 我也试过从头开始创建一个新屏幕。
- 我已经在 Stack Navigator 中将屏幕作为初始路径进行了测试,并且 它工作得很好,但我仍然无法让旋转木马在 屏幕加载。
- 我也试过切换到基于 class 的 React 组件 没有帮助。
代码
带轮播的组件
import React, { useState } from "react";
import { View, Text } from "react-native";
import { useDispatch } from "react-redux";
import styles from "./StatSelectorStartComp.style";
import HeaderText from "~/app/Components/HeaderText/HeaderText";
import Carousel from "react-native-snap-carousel";
import LargeButton from "~/app/Components/Buttons/LargeButton/LargeButton";
import NavigationService from "~/app/services/NavigationService";
import { saveStartCompStatCategory } from "~/app/Redux/actions/dailyCompActions";
const StatSelectorStartComp = ({}) => {
const dispatch = useDispatch();
const ENTRIES1 = ["Kills", "Wins", "K/D", "Win %"];
const [selectedStat, setSelectedStat] = useState(ENTRIES1[0]);
const _renderItem = ({ item, index }) => {
return (
<View style={styles.slide}>
<Text style={styles.compSelectStatCarousel}>{item}</Text>
</View>
);
};
return (
<View style={styles.container}>
<View style={styles.headerTextView}>
<HeaderText header={"Configure Competition"} />
</View>
<Text style={styles.h5Secondary}> Which stat will you track?</Text>
<View style={styles.selectStatView}>
<Text style={styles.mediumGreyedOut}>Most {selectedStat} Wins</Text>
<Carousel
ref={c => {
_carousel = c;
}}
data={ENTRIES1}
renderItem={_renderItem}
sliderWidth={375}
itemWidth={100}
onSnapToItem={index => {
setSelectedStat(ENTRIES1[index]);
}}
/>
</View>
<View style={styles.buttonView}>
<LargeButton
onPress={() => {
dispatch(saveStartCompStatCategory(selectedStat));
NavigationService.navigate("CompAddFriends");
}}
buttonText="Add Friends"
/>
</View>
</View>
);
};
export default StatSelectorStartComp;
轮播组件的样式
import { StyleSheet } from "react-native";
import { backgroundColor } from "~/app/Constants";
import {
h5Secondary,
mediumGreyedOut,
compSelectStatCarousel
} from "~/app/FontConstants";
export default StyleSheet.create({
container: {
flex: 1,
justifyContent: "space-between",
backgroundColor
},
headerTextView: {
flex: 1
},
h5Secondary,
selectStatView: {
flex: 3
},
mediumGreyedOut,
compSelectStatCarousel,
buttonView: {
flex: 2
}
});
React 导航配置
const StartCompStack = createStackNavigator({
StartFriendsComp: {
screen: StartFriendsComp
},
StatSelectorStartComp: {
screen: CarouselTest
},
CompAddFriends: {
screen: CompAddFriends
},
FinalCompScreen: {
screen: FinalCompScreen
}
});
const ProfileStack = createStackNavigator({
Profile: {
screen: ProfileScreen
},
Settings: {
screen: SettingsScreen
}
});
const BottomTabNav = createBottomTabNavigator(
{
Home: {
screen: HomeScreen
},
Competitions: {
screen: Competitions
},
StartComp: {
screen: StartCompStack,
navigationOptions: () => ({
tabBarVisible: false
})
},
CompScreen: {
screen: CompScreen
},
Friends: {
screen: FriendsDrawer
},
Profile: {
screen: ProfileStack
},
FacebookFriendsList
},
{
tabBarComponent: CustomTabNav,
initialRouteName: "Home"
}
);
图片概括问题
加载屏幕时,轮播未呈现
在旋转木马上滑动后
我们的项目也遇到了同样的问题,一个小技巧可以帮助我们。我们已将默认加载状态设置为 true,并在 componentDidMount 中将状态设置为 false 以显示 Carousel
试试这个,它可能对你有帮助
state = { loading: true };
componentDidMount() {
setTimeout(() => {
this.setState({ loading: false });
}, 10);
}
render() {
if(this.state.loading) {
return null;
}
// return component render which contain Carousel
.........
}
<Carousel
ref={c => {
_carousel = c;
}}
data={ENTRIES1}
renderItem={_renderItem}
sliderWidth={375}
itemWidth={100}
onSnapToItem={index => {
setSelectedStat(ENTRIES1[index]);
}}
/>
</
我认为问题在于给出静态高度和宽度。尝试动态计算高度和宽度,然后显示它。这里的动态是指计算设备的高度和宽度,然后对其进行计算。
有一个实验性配置(当前为 v3.8.4)- removeClippedSubviews
- 默认设置为 true
。将其设置为 false
解决了我的问题。
我强烈建议不要使用延迟,因为它不是确定性的,并且会因设备而异。
感谢在评论中写下这篇文章的@auticcat。
我通过简单地使用 removeClippedSubviews={false}
解决了它您可以创建自己的自定义轮播。 Carousel 最终结果如下所示-
goToNextPage = () => {
const childlenth = this.getCustomData().length;
selectedIndex = selectedIndex + 1;
this.clearTimer();
if (selectedIndex === childlenth) {
this.scrollRef.current.scrollTo({ offset: 0, animated: false, nofix: true });
selectedIndex = 1;
}
this.scrollRef.current.scrollTo({
animated: true,
x: this.props.childWidth * selectedIndex,
});
this.setUpTimer();
}
// pushing 1st element at last
getCustomData() {
const {data} = this.props;
const finaldata = [];
finaldata.push(...data);
finaldata.push(data[0]);
return finaldata;
}
这是循环轮播背后使用的主要逻辑。 在这里,我们再次推送列表中的第一个项目,然后当滚动到达最后一个位置时,我们让滚动视图滚动到第一个位置,因为现在第一个和最后一个元素相同,我们用这样的动画滚动到第一个位置
this.scrollRef.current.scrollTo({ offset: 0, animated: false, nofix: true });
如需进一步参考,请查看所提供的 link。