我创建了流派(多首歌曲数据并将歌曲数据传递给我项目中的同一个 PlayerScreen.js,但我开始出现 TypeErrors 和警告:
可能的未处理承诺拒绝(id:3):TypeError:无法读取 null 的属性“scrollToOffset”类型错误:无法读取 null 的属性“scrollToOffset”
例如,我有流行、乡村、摇滚、嘻哈等流派,现在我在所有流派中都有相同的歌曲数组,我用相同的代码创建了不同的播放器屏幕。但我相信没有做正确的事。请问我怎样才能拥有不同的歌曲数据(流派)并使用一个播放器屏幕播放歌曲?
这是我的代码。hiphopData.js:
const hiphopsongs = [
{
title: "death bed",
artist: "Powfu",
genre: "Pop",
artwork: require("../../../assets/album-arts/death-bed.jpg"),
url: "https://github.com/ShivamJoker/sample-songs/raw/master/death%20bed.mp3",
id: "1",
},
{
title: "bad liar",
artist: "Imagine Dragons",
artwork: require("../../../assets/album-arts/bad-liar.jpg"),
url: "https://github.com/ShivamJoker/sample-songs/raw/master/Bad%20Liar.mp3",
id: "2",
},
{
title: "faded",
artist: "Alan Walker",
genre: "Pop",
artwork: require("../../../assets/album-arts/faded.jpg"),
url: "https://github.com/ShivamJoker/sample-songs/raw/master/Faded.mp3",
id: "3",
},
{
title: "hate me",
artist: "Ellie Goulding",
artwork: require("../../../assets/album-arts/hate-me.jpg"),
url: "https://github.com/ShivamJoker/sample-songs/raw/master/Hate%20Me.mp3",
id: "4",
},
{
title: "Solo",
artist: "Clean Bandit",
artwork: require("../../../assets/album-arts/solo.jpg"),
url: "https://github.com/ShivamJoker/sample-songs/raw/master/Solo.mp3",
id: "5",
},
{
title: "without me",
artist: "Halsey",
artwork: require("../../../assets/album-arts/without-me.jpg"),
url: "https://github.com/ShivamJoker/sample-songs/raw/master/Without%20Me.mp3",
id: "6",
},
];
export default hiphopsongs;
hiphopPlayerScreen.js:
import React, {useRef, useEffect, useState} from 'react';
import {
View,
SafeAreaView,
Text,
Image,
FlatList,
Dimensions,
Animated,
StyleSheet,
TouchableOpacity,
} from 'react-native';
import { useNavigation } from '@react-navigation/native';
import TrackPlayer, {
Capability,
useTrackPlayerEvents,
usePlaybackState,
TrackPlayerEvents,
STATE_PLAYING,
Event,
} from 'react-native-track-player';
import songs from '../../components/TracksData/hipHopData';
import Controller from '../../components/Controller';
import SliderComp from '../../components/SliderComp';
import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons';
const {width, height} = Dimensions.get('window');
// const events = [
// TrackPlayerEvents.PLAYBACK_STATE,
// TrackPlayerEvents.PLAYBACK_ERROR
// ];
export default function PlayerScreen() {
const navigation = useNavigation();
const scrollX = useRef(new Animated.Value(0)).current;
const slider = useRef(null);
const isPlayerReady = useRef(false);
const index = useRef(0);
const [songIndex, setSongIndex] = useState(0);
const isItFromUser = useRef(true);
// for tranlating the album art
const position = useRef(Animated.divide(scrollX, width)).current;
const playbackState = usePlaybackState();
useEffect(() => {
// position.addListener(({ value }) => {
// console.log(value);
// });
scrollX.addListener(({value}) => {
const val = Math.round(value / width);
setSongIndex(val);
});
TrackPlayer.setupPlayer().then(async () => {
// The player is ready to be used
console.log('Player ready');
// add the array of songs in the playlist
await TrackPlayer.reset();
await TrackPlayer.add(songs);
TrackPlayer.play();
isPlayerReady.current = true;
await TrackPlayer.updateOptions({
stopWithApp: false,
alwaysPauseOnInterruption: true,
capabilities: [
Capability.Play,
Capability.Pause,
Capability.SkipToNext,
Capability.SkipToPrevious,
],
});
//add listener on track change
TrackPlayer.addEventListener(Event.PlaybackTrackChanged, async (e) => {
console.log('song ended', e);
const trackId = (await TrackPlayer.getCurrentTrack()) - 1; //get the current id
console.log('track id', trackId, 'index', index.current);
if (trackId !== index.current) {
setSongIndex(trackId);
isItFromUser.current = false;
if (trackId > index.current) {
goNext();
} else {
goPrv();
}
setTimeout(() => {
isItFromUser.current = true;
}, 200);
}
// isPlayerReady.current = true;
});
//monitor intterupt when other apps start playing music
TrackPlayer.addEventListener(Event.RemoteDuck, (e) => {
// console.log(e);
if (e.paused) {
// if pause true we need to pause the music
TrackPlayer.pause();
} else {
TrackPlayer.play();
}
});
});
return () => {
scrollX.removeAllListeners();
TrackPlayer.destroy();
// exitPlayer();
};
}, []);
// change the song when index changes
useEffect(() => {
if (isPlayerReady.current && isItFromUser.current) {
TrackPlayer.skip(songs[songIndex].id)
.then((_) => {
console.log('changed track');
})
.catch((e) => console.log('error in changing track ', e));
}
index.current = songIndex;
}, [songIndex]);
const exitPlayer = async () => {
try {
await TrackPlayer.stop();
} catch (error) {
console.error('exitPlayer', error);
}
};
const goNext = async () => {
slider.current.scrollToOffset({
offset: (index.current + 1) * width,
});
await TrackPlayer.play();
};
const goPrv = async () => {
slider.current.scrollToOffset({
offset: (index.current - 1) * width,
});
await TrackPlayer.play();
};
const renderItem = ({index, item}) => {
return (
<Animated.View
style={{
alignItems: 'center',
width: width,
transform: [
{
translateX: Animated.multiply(
Animated.add(position, -index),
-100,
),
},
],
}}>
<Animated.Image
source={item.artwork}
style={{width: 320, height: 320, borderRadius: 5}}
/>
</Animated.View>
);
};
return (
<SafeAreaView style={styles.container}>
<SafeAreaView style={{height: 320}}>
<Animated.FlatList
ref={slider}
horizontal
pagingEnabled
showsHorizontalScrollIndicator={false}
scrollEventThrottle={16}
data={songs}
renderItem={renderItem}
keyExtractor={(item) => item.id}
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {x: scrollX}}}],
{useNativeDriver: true},
)}
/>
</SafeAreaView>
<TouchableOpacity
style={styles.genreContainer}
onPress={() => navigation.navigate('Genre')}
>
<SimpleLineIcons name="playlist" size={20} color='#fff' />
<Text style={styles.genre}> Genre</Text>
</TouchableOpacity>
<View>
<Text style={styles.title}>{songs[songIndex].title}</Text>
<Text style={styles.artist}>{songs[songIndex].artist}</Text>
</View>
<SliderComp />
<Controller onNext={goNext} onPrv={goPrv} />
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
justifyContent: 'space-evenly',
alignItems: 'center',
height: height,
maxHeight: 600,
backgroundColor: '#030303'
},
genreContainer: {
flexDirection: 'row',
},
genre: {
fontSize: 18,
textAlign: 'center',
fontWeight: '600',
textTransform: 'capitalize',
color: '#ffffff',
},
title: {
fontSize: 28,
textAlign: 'center',
fontWeight: '600',
textTransform: 'capitalize',
color: '#ffffff',
},
artist: {
fontSize: 18,
textAlign: 'center',
color: '#ffffff',
textTransform: 'capitalize',
},
});
我对我创建的所有类型都这样做了,但我觉得这不是正确的方法。请帮助我将所有流派数据传递到一个播放器屏幕。