使用 react-native-track-player 从 flatlist 播放选定的歌曲
Posted
技术标签:
【中文标题】使用 react-native-track-player 从 flatlist 播放选定的歌曲【英文标题】:Using react-native-track-player to play selected song from flatlist 【发布时间】:2021-04-07 14:23:54 【问题描述】:我不知道如何从平面列表中播放选定的曲目/歌曲,我已经有一个 playerscreen.js,我可以在其中播放我的歌曲数组中的歌曲。我想实现用户搜索歌曲并从平面列表中选择列表中播放歌曲。下面是我的 songlist.js
const Songlist = () =>
const [loading, setLoading] = useState(false);
const navigation = useNavigation();
renderFooter = () =>
if (!loading) return null
return (
<View
style=
paddingVertical: 20,
borderTopWidth: 1,
borderColor: '#CED0CE',
>
<ActivityIndicator animating size='large' />
</View>
)
renderSeparator = () =>
return (
<View
style=
height: 1,
width: '86%',
backgroundColor: '#CED0CE',
marginLeft: '5%',
/>
)
return (
<View>
<FlatList
data=songs
keyExtractor=item => item.id
renderItem=( item, index ) => (
<TouchableOpacity
onPress=() => navigation.navigate('Player')
>
<View
style=
flexDirection: 'row',
padding: 16,
alignItems: 'center',
>
<Avatar
source= uri: item.artwork.thumbnail
size='giant'
style= marginRight: 16
/>
<Text
category='s1'
style=color: '#000'
>`$item.title`</Text>
</View>
<Text
category='s2'
style=color: '#999', marginHorizontal: 80, bottom: 20
>Genre: `$item.genre`</Text>
</TouchableOpacity>
)
ItemSeparatorComponent=renderSeparator
ListFooterComponent=renderFooter
/>
</View>
);
export default Songlist;
这是我最初的 playerscreen.js
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>
);
【问题讨论】:
【参考方案1】:import React from 'react';
import SafeAreaView, View, FlatList, StyleSheet, Text, StatusBar, ScrollView, TouchableOpacity from 'react-native';
import Sound from 'react-native-sound';
const MusicApp = () =>
const DATA = [
title: 'Advertising Local',
isRequire: true,
url: require('./resource/advertising.mp3'),
,
title: 'Advertising URL',
url:
'https://raw.githubusercontent.com/zmxv/react-native-sound-demo/master/advertising.mp3',
,
title: 'Hosana',
isRequire: true,
url: require('./Hosana.mp3'),
,
title: 'Play aac sound from remote URL',
url:
'https://raw.githubusercontent.com/zmxv/react-native-sound-demo/master/pew2.aac',
,
title: 'Frog wav sound from Local',
isRequire: true,
url: require('./resource/frog.wav'),
,
title: 'Frog wav sound from remote URL',
url:
'https://raw.githubusercontent.com/zmxv/react-native-sound-demo/master/frog.wav',
,
];
let sound;
const playSound =(item, id)=>
console.log("the url is "+ item.url);
if(item.url !=1)
sound = new Sound(item.url, '', (error, _sound) =>
if (error)
alert('error' + error.message);
return;
stopSound
sound.play(() =>
sound.release();
);
);
else
sound = new Sound(item.url, (error, _sound) =>
if (error)
alert('error' + error.message);
return;
stopSound
sound.play(() =>
sound.release();
);
);
const stopSound =(index)=>
sound.stop(() =>
console.log('Stop');
);
const renderItem = ( item, index ) => (
<ScrollView style=flex: 1>
<View style=styles.item>
<Text style=styles.title> item.title </Text>
<TouchableOpacity onPress=()=>playSound(item, index) style=padding: 10, backgroundColor: 'blue'><Text>Play</Text></TouchableOpacity>
<TouchableOpacity onPress=()=>stopSound(index) style=padding: 10, backgroundColor: 'red'><Text>Stop</Text></TouchableOpacity>
</View>
</ScrollView>
);
return (
<SafeAreaView style=styles.container>
<FlatList
data=DATA
renderItem=renderItem
keyExtractor=item => item.id
/>
</SafeAreaView>
);
const styles = StyleSheet.create(
container:
flex: 1,
marginTop: StatusBar.currentHeight || 0,
,
item:
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
,
title:
fontSize: 20,
,
);
export default MusicApp;
注意: 使用 yarn add react-native-sound 或 npm install react-native-sound。 其次,音乐的来源有两种——远程url和本地文件路径,请确保在运行前适当修改本地文件路径
【讨论】:
以上是关于使用 react-native-track-player 从 flatlist 播放选定的歌曲的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)